diff --git a/.run/Run on Raspberry Pi.run.xml b/.run/Run on Raspberry Pi.run.xml
new file mode 100644
index 00000000..2109d0bf
--- /dev/null
+++ b/.run/Run on Raspberry Pi.run.xml
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libraries/pi4j-library-gpiod/generate-headers.sh b/libraries/pi4j-library-gpiod/generate-headers.sh
new file mode 100644
index 00000000..8c2e033e
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/generate-headers.sh
@@ -0,0 +1,2 @@
+#!/usr/bin/env bash
+javac src/main/java/com/pi4j/library/gpiod/internal/GpioD.java -h src/main/native
diff --git a/libraries/pi4j-library-gpiod/pom.xml b/libraries/pi4j-library-gpiod/pom.xml
new file mode 100644
index 00000000..5d29a68b
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/pom.xml
@@ -0,0 +1,365 @@
+
+
+ 4.0.0
+
+ com.pi4j
+ pi4j-library
+ 2.4.0-SNAPSHOT
+ ../pi4j-library/pom.xml
+
+
+
+ pi4j-library-gpiod
+ Pi4J :: LIBRARY :: JNI Wrapper for GpioD Library
+ Pi4J wrapper for the GpioD library
+ jar
+
+
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+
+
+ org.slf4j
+ slf4j-simple
+ ${slf4j.version}
+ test
+
+
+
+
+
+
+
+
+
+ ${project.build.directory}
+ false
+
+ LICENSE.txt
+ NOTICE.txt
+ README.md
+ lib/armhf/pi4j-gpiod/libpi4j-gpiod.so
+ lib/armhf/pi4j-gpiod/libgpiod.so
+ lib/aarch64/pi4j-gpiod/libpi4j-gpiod.so
+ lib/aarch64/pi4j-gpiod/libgpiod.so
+
+
+
+ src/main/resources
+ false
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+
+
+ enforce-native-jni-file--exist
+
+ enforce
+
+ prepare-package
+
+
+
+
+
+ ${project.build.outputDirectory}/lib/armhf/pi4j-gpiod/libpi4j-gpiod.so
+ ${project.build.outputDirectory}/lib/armhf/pi4j-gpiod/libgpiod.so
+
+ ${project.build.outputDirectory}/lib/aarch64/pi4j-gpiod/libpi4j-gpiod.so
+ ${project.build.outputDirectory}/lib/aarch64/pi4j-gpiod/libgpiod.so
+
+
+
+ true
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+
+
+ transfer-compiled-pi4j-jar
+ install
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pi4j-attach-native
+ package
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ package
+
+ copy-dependencies
+
+
+ runtime
+ com.pi4j
+ ${project.build.directory}/dependencies
+ false
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ default
+
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ download-jni-dependency
+ validate
+
+ copy
+
+
+
+
+
+
+
+ ${project.groupId}
+ ${project.artifactId}
+ ${project.version}
+ armhf
+ so
+ true
+ ${project.build.directory}/lib/armhf/pi4j-gpiod
+ libpi4j-gpiod.so
+
+
+ ${project.groupId}
+ ${project.artifactId}
+ ${project.version}
+ armhf
+ so
+ true
+ ${project.build.directory}/lib/armhf/pi4j-gpiod
+ libgpiod.so
+
+
+
+
+
+
+ ${project.groupId}
+ ${project.artifactId}
+ ${project.version}
+ so
+ aarch64
+ true
+ ${project.build.directory}/lib/aarch64/pi4j-gpiod
+ libpi4j-gpiod.so
+
+
+ ${project.groupId}
+ ${project.artifactId}
+ ${project.version}
+ so
+ aarch64
+ true
+ ${project.build.directory}/lib/aarch64/pi4j-gpiod
+ libgpiod.so
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ native
+
+
+ release-build
+
+
+
+
+
+ maven-antrun-plugin
+
+
+
+ pi4j-prepare-native
+ generate-resources
+
+
+
+
+
+
+
+
+
+
+
+
+
+ run
+
+
+
+
+
+
+
+ pi4j-build-native
+ generate-resources
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/CWrapper.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/CWrapper.java
new file mode 100644
index 00000000..31826926
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/CWrapper.java
@@ -0,0 +1,28 @@
+package com.pi4j.library.gpiod.internal;
+
+import java.util.Objects;
+
+public class CWrapper {
+ private long cPointer;
+
+ public CWrapper(long cPointer) {
+ this.cPointer = cPointer;
+ }
+
+ long getCPointer() {
+ return cPointer;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ CWrapper cWrapper = (CWrapper) o;
+ return cPointer == cWrapper.cPointer;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(cPointer);
+ }
+}
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioChip.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioChip.java
new file mode 100644
index 00000000..60640fa7
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioChip.java
@@ -0,0 +1,53 @@
+package com.pi4j.library.gpiod.internal;
+
+import java.io.Closeable;
+
+/**
+ *
GpioChip
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioChip extends CWrapper implements Closeable {
+
+ public GpioChip(long cPointer) {
+ super(cPointer);
+ }
+
+ public void close() {
+ GpioD.chipClose(this);
+ }
+
+ public String getName() {
+ return GpioD.chipGetName(this);
+ }
+
+ public String getLabel() {
+ return GpioD.chipGetLabel(this);
+ }
+
+ public int getNumLines() {
+ return GpioD.chipGetNumLines(this);
+ }
+
+ public GpioLine getLine(int offset) {
+ return GpioD.chipGetLine(this, offset);
+ }
+
+ public GpioLineBulk getLines(int[] offsets) {
+ GpioLineBulk bulk = new GpioLineBulk();
+ GpioD.chipGetLines(this, offsets, bulk);
+ return bulk;
+ }
+
+ public GpioLineBulk getLines() {
+ GpioLineBulk bulk = new GpioLineBulk();
+ GpioD.chipGetAllLines(this, bulk);
+ return bulk;
+ }
+
+ public GpioLine getLine(String name) {
+ return GpioD.chipGetLine(this, name);
+ }
+
+}
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioChipIterator.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioChipIterator.java
new file mode 100644
index 00000000..1be9c4c6
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioChipIterator.java
@@ -0,0 +1,72 @@
+package com.pi4j.library.gpiod.internal;
+
+import java.util.Iterator;
+
+/**
+ * GpioChipIterator
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioChipIterator extends CWrapper implements Iterator {
+
+ private boolean noCloseCurrent;
+ private GpioChip next;
+ private GpioChip current;
+
+ GpioChipIterator(long cPointer) {
+ super(cPointer);
+ }
+
+ public GpioChipIterator() {
+ this(GpioD.chipIterNew());
+ }
+
+
+ @Override
+ protected void finalize() {
+ if(next == null) {
+ if(noCloseCurrent) {
+ GpioD.chipIterFreeNoClose(this);
+ } else {
+ GpioD.chipIterFree(this);
+ }
+ } else {
+ if(!noCloseCurrent) {
+ GpioD.chipClose(current);
+ }
+ GpioD.chipIterFree(this);
+ }
+ }
+
+ @Override
+ public boolean hasNext() {
+ if(next == null) {
+ next = GpioD.chipIterNextNoClose(this);
+ }
+ return next != null;
+ }
+
+ @Override
+ public GpioChip next() {
+ if(next == null) {
+ if(noCloseCurrent) {
+ current = GpioD.chipIterNextNoClose(this);
+ } else {
+ current = GpioD.chipIterNext(this);
+ }
+ } else {
+ if(current != null && !noCloseCurrent) {
+ GpioD.chipClose(current);
+ }
+ current = next;
+ noCloseCurrent = false;
+ next = null;
+ }
+ return current;
+ }
+
+ public void noCloseCurrent() {
+ this.noCloseCurrent = true;
+ }
+}
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioD.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioD.java
new file mode 100644
index 00000000..2e7a9764
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioD.java
@@ -0,0 +1,817 @@
+package com.pi4j.library.gpiod.internal;
+
+import com.pi4j.library.gpiod.util.NativeLibraryLoader;
+
+import java.util.Arrays;
+
+/**
+ * GpioD interface.
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioD {
+ // C library: https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/tree/include/gpiod.h?h=v1.6.x
+
+ private GpioD() {
+ // forbid object construction
+ }
+
+ static {
+ // Load the platform library
+ NativeLibraryLoader.load("libgpiod.so", "pi4j-gpiod");
+ NativeLibraryLoader.load("libpi4j-gpiod.so", "pi4j-gpiod");
+ }
+
+ static GpioChip chipOpen(String path) {
+ Long ptr = c_gpiod_chip_open(path);
+ if(ptr == null) {
+ throw new GpioDException("c_gpiod_chip_open failed!");
+ }
+ return new GpioChip(ptr);
+ }
+
+ private static native Long c_gpiod_chip_open(String path);
+
+ static void chipClose(GpioChip chip) {
+ c_gpiod_chip_close(chip.getCPointer());
+ }
+
+ private static native void c_gpiod_chip_close(long chipPtr);
+
+ static String chipGetName(GpioChip chip) {
+ return c_gpiod_chip_name(chip.getCPointer());
+ }
+
+ private static native String c_gpiod_chip_name(long chipPtr);
+
+ static String chipGetLabel(GpioChip chip) {
+ return c_gpiod_chip_label(chip.getCPointer());
+ }
+
+ private static native String c_gpiod_chip_label(long chipPtr);
+
+ static int chipGetNumLines(GpioChip chip) {
+ return c_gpiod_chip_num_lines(chip.getCPointer());
+ }
+
+ private static native int c_gpiod_chip_num_lines(long chipPtr);
+
+ static GpioLine chipGetLine(GpioChip chip, int offset) {
+ Long linePtr = c_gpiod_chip_get_line(chip.getCPointer(), offset);
+ if (linePtr == null) {
+ throw new GpioDException("c_gpiod_chip_get_line failed!");
+ }
+ return new GpioLine(linePtr);
+ }
+ private static native Long c_gpiod_chip_get_line(long chipPtr, int offset);
+
+ static void chipGetLines(GpioChip chip, int[] offsets, GpioLineBulk lineBulk) {
+ if(c_gpiod_chip_get_lines(chip.getCPointer(), offsets, offsets.length, lineBulk.getCPointer()) < 0) {
+ throw new GpioDException("c_gpiod_chip_get_lines failed!");
+ }
+ }
+
+ private static native int c_gpiod_chip_get_lines(long chipPtr, int[] offsets, int numOffsets, long lineBulkPtr);
+
+ static void chipGetAllLines(GpioChip chip, GpioLineBulk lineBulk) {
+ if(c_gpiod_chip_get_all_lines(chip.getCPointer(), lineBulk.getCPointer()) < 0) {
+ throw new GpioDException("c_gpiod_chip_get_all_lines failed!");
+ }
+ }
+
+ private static native int c_gpiod_chip_get_all_lines(long chipPtr, long lineBulkPtr);
+
+ static GpioLine chipGetLine(GpioChip chip, String name) {
+ Long linePtr = c_gpiod_chip_find_line(chip.getCPointer(), name);
+ if (linePtr == null) {
+ throw new GpioDException("c_gpiod_chip_find_line failed!");
+ }
+ return new GpioLine(linePtr);
+ }
+
+ private static native Long c_gpiod_chip_find_line(long chipPtr, String name);
+
+ static void lineBulkFree(GpioLineBulk lineBulk) {
+ c_gpiod_line_bulk_free(lineBulk.getCPointer());
+ }
+
+ private static native void c_gpiod_line_bulk_free(long lineBulkPtr);
+
+ private static native void gpiod_line_bulk_init(long lineBulkPtr);
+
+ static long lineBulkNew() {
+ Long ptr = c_gpiod_line_bulk_new();
+ if(ptr == null) {
+ throw new GpioDException("c_gpiod_line_bulk_new failed!");
+ }
+ gpiod_line_bulk_init(ptr);
+ return ptr;
+ }
+
+ private static native Long c_gpiod_line_bulk_new();
+
+ static void lineBulkAdd(GpioLineBulk lineBulk, GpioLine line) {
+ c_gpiod_line_bulk_add(lineBulk.getCPointer(), line.getCPointer());
+ }
+
+ private static native void c_gpiod_line_bulk_add(long lineBulkPtr, long linePtr);
+
+ static GpioLine lineBulkGetLine(GpioLineBulk lineBulk, int offset) {
+ return new GpioLine(c_gpiod_line_bulk_get_line(lineBulk.getCPointer(), offset));
+ }
+
+ private static native long c_gpiod_line_bulk_get_line(long lineBulkPtr, int offset);
+
+ static int lineBulkGetNumLines(GpioLineBulk lineBulk) {
+ return c_gpiod_line_bulk_num_lines(lineBulk.getCPointer());
+ }
+
+ private static native int c_gpiod_line_bulk_num_lines(long lineBulkPtr);
+
+
+ public enum LINE_DIRECTION {
+ INPUT(1), OUTPUT(2);
+ final int val;
+
+ public int getVal() {
+ return val;
+ }
+
+ LINE_DIRECTION(int val) {
+ this.val = val;
+ }
+
+ static LINE_DIRECTION fromInt(int val) {
+ for (LINE_DIRECTION dir : LINE_DIRECTION.values()) {
+ if (dir.val == val) {
+ return dir;
+ }
+ }
+ throw new IllegalStateException("Unexpected LINE_DIRECTION value: " + val);
+ }
+ }
+
+ public enum LINE_ACTIVE_STATE {
+ HIGH(1), LOW(2);
+ final int val;
+
+ public int getVal() {
+ return val;
+ }
+
+ LINE_ACTIVE_STATE(int val) {
+ this.val = val;
+ }
+
+ static LINE_ACTIVE_STATE fromInt(int val) {
+ for (LINE_ACTIVE_STATE dir : LINE_ACTIVE_STATE.values()) {
+ if (dir.val == val) {
+ return dir;
+ }
+ }
+ throw new IllegalStateException("Unexpected LINE_ACTIVE_STATE value: " + val);
+ }
+ }
+
+ public enum LINE_BIAS {
+ AS_IS(1), DISABLE(2), PULL_UP(3), PULL_DOWN(4);
+ final int val;
+
+ public int getVal() {
+ return val;
+ }
+
+ LINE_BIAS(int val) {
+ this.val = val;
+ }
+
+ static LINE_BIAS fromInt(int val) {
+ for (LINE_BIAS dir : LINE_BIAS.values()) {
+ if (dir.val == val) {
+ return dir;
+ }
+ }
+ throw new IllegalStateException("Unexpected LINE_BIAS value: " + val);
+ }
+ }
+
+ static int lineGetOffset(GpioLine line) {
+ return c_gpiod_line_offset(line.getCPointer());
+ }
+
+ private static native int c_gpiod_line_offset(long linePtr);
+
+ static String lineGetName(GpioLine line) {
+ return c_gpiod_line_name(line.getCPointer());
+ }
+
+ private static native String c_gpiod_line_name(long linePtr);
+
+ static String lineGetConsumer(GpioLine line) {
+ return gpiod_line_consumer(line.getCPointer());
+ }
+
+ private static native String gpiod_line_consumer(long linePtr);
+
+ static LINE_DIRECTION lineGetDirection(GpioLine line) {
+ return LINE_DIRECTION.fromInt(c_gpiod_line_direction(line.getCPointer()));
+ }
+
+ private static native int c_gpiod_line_direction(long linePtr);
+
+ static LINE_ACTIVE_STATE lineGetActiveState(GpioLine line) {
+ return LINE_ACTIVE_STATE.fromInt(c_gpiod_line_active_state(line.getCPointer()));
+ }
+
+ private static native int c_gpiod_line_active_state(long linePtr);
+
+ static LINE_BIAS lineGetBias(GpioLine line) {
+ return LINE_BIAS.fromInt(c_gpiod_line_bias(line.getCPointer()));
+ }
+
+ private static native int c_gpiod_line_bias(long linePtr);
+
+ static boolean lineIsUsed(GpioLine line) {
+ return c_gpiod_line_is_used(line.getCPointer());
+ }
+
+ private static native boolean c_gpiod_line_is_used(long linePtr);
+
+ static boolean lineIsOpenDrain(GpioLine line) {
+ return c_gpiod_line_is_open_drain(line.getCPointer());
+ }
+
+ private static native boolean c_gpiod_line_is_open_drain(long linePtr);
+
+ static boolean lineIsOpenSource(GpioLine line) {
+ return c_gpiod_line_is_open_source(line.getCPointer());
+ }
+
+ private static native boolean c_gpiod_line_is_open_source(long linePtr);
+
+ static void lineUpdate(GpioLine line) {
+ if(c_gpiod_line_update(line.getCPointer()) < 0) {
+ throw new GpioDException("c_gpiod_line_update failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_update(long linePtr);
+
+ public enum LINE_REQUEST {
+ DIRECTION_AS_IS(1), DIRECTION_INPUT(2), DIRECTION_OUTPUT(3), EVENT_FALLING_EDGE(4),
+ EVENT_RISING_EDGE(5), EVENT_BOTH_EDGES(6);
+ final int val;
+
+ public int getVal() {
+ return val;
+ }
+
+ LINE_REQUEST(int val) {
+ this.val = val;
+ }
+
+ static LINE_REQUEST fromInt(int val) {
+ for (LINE_REQUEST dir : LINE_REQUEST.values()) {
+ if (dir.val == val) {
+ return dir;
+ }
+ }
+ throw new IllegalStateException("Unexpected LINE_REQUEST value: " + val);
+ }
+ }
+
+ public enum LINE_REQUEST_FLAG {
+ OPEN_DRAIN((byte) 1), OPEN_SOURCE((byte) (1 << 1)), ACTIVE_LOW((byte) (1 << 2)), BIAS_DISABLE((byte) (1 << 3)),
+ BIAS_PULL_DOWN((byte) (1 << 4)), BIAS_PULL_UP((byte) (1 << 5));
+ final byte val;
+
+ LINE_REQUEST_FLAG(byte val) {
+ this.val = val;
+ }
+
+ public byte getVal() {
+ return val;
+ }
+
+ static LINE_REQUEST_FLAG fromByte(byte val) {
+ for (LINE_REQUEST_FLAG dir : LINE_REQUEST_FLAG.values()) {
+ if (dir.val == val) {
+ return dir;
+ }
+ }
+ throw new IllegalStateException("Unexpected LINE_REQUEST_FLAG value: " + val);
+ }
+ }
+
+ static void lineRequest(GpioLine line, GpioLineRequest request, int defaultVal) {
+ if(c_gpiod_line_request(line.getCPointer(), request.getCPointer(), defaultVal) < 0) {
+ throw new GpioDException("c_gpiod_line_request failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request(long linePtr, long lineRequestPtr, int default_val);
+
+ static void lineRequestInput(GpioLine line, String consumer) {
+ if(c_gpiod_line_request_input(line.getCPointer(), consumer) < 0) {
+ throw new GpioDException("c_gpiod_line_request_input failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_input(long linePtr, String consumer);
+
+ static void lineRequestOutput(GpioLine line, String consumer, int defaultVal) {
+ if(c_gpiod_line_request_output(line.getCPointer(), consumer, defaultVal) < 0) {
+ throw new GpioDException("c_gpiod_line_request_output failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_output(long linePtr, String consumer, int default_val);
+
+ static void lineRequestRisingEdgeEvents(GpioLine line, String consumer) {
+ if(c_gpiod_line_request_rising_edge_events(line.getCPointer(), consumer) < 0) {
+ throw new GpioDException("c_gpiod_line_request_rising_edge_events failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_rising_edge_events(long linePtr, String consumer);
+
+ static void lineRequestFallingEdgeEvents(GpioLine line, String consumer) {
+ if(c_gpiod_line_request_falling_edge_events(line.getCPointer(), consumer) < 0) {
+ throw new GpioDException("c_gpiod_line_request_falling_edge_events failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_falling_edge_events(long linePtr, String consumer);
+
+ static void lineRequestBothEdgeEvents(GpioLine line, String consumer) {
+ if(c_gpiod_line_request_both_edges_events(line.getCPointer(), consumer) < 0) {
+ throw new GpioDException("c_gpiod_line_request_both_edges_events failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_both_edges_events(long linePtr, String consumer);
+
+ static void lineRequestInputFlags(GpioLine line, String consumer, int flags) {
+ if(c_gpiod_line_request_input_flags(line.getCPointer(), consumer, flags) < 0) {
+ throw new GpioDException("c_gpiod_line_request_input_flags failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_input_flags(long linePtr, String consumer, int flags);
+
+ static void lineRequestOutputFlags(GpioLine line, String consumer, int flags, int defaultVal) {
+ if(c_gpiod_line_request_output_flags(line.getCPointer(), consumer, flags, defaultVal) < 0) {
+ throw new GpioDException("c_gpiod_line_request_output_flags failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_output_flags(long linePtr, String consumer, int flags, int default_val);
+
+ static void lineRequestRisingEdgeEventsFlags(GpioLine line, String consumer, int flags) {
+ if(c_gpiod_line_request_rising_edge_events_flags(line.getCPointer(), consumer, flags) < 0) {
+ throw new GpioDException("c_gpiod_line_request_rising_edge_events_flags failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_rising_edge_events_flags(long linePtr, String consumer, int flags);
+
+ static void lineRequestFallingEdgeEventsFlags(GpioLine line, String consumer, int flags) {
+ if(c_gpiod_line_request_falling_edge_events_flags(line.getCPointer(), consumer, flags) < 0) {
+ throw new GpioDException("c_gpiod_line_request_falling_edge_events_flags failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_falling_edge_events_flags(long linePtr, String consumer, int flags);
+
+ static void lineRequestBothEdgeEventsFlags(GpioLine line, String consumer, int flags) {
+ if(c_gpiod_line_request_both_edges_events_flags(line.getCPointer(), consumer, flags) < 0) {
+ throw new GpioDException("c_gpiod_line_request_both_edges_events_flags failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_both_edges_events_flags(long linePtr, String consumer, int flags);
+
+ static void lineRequestBulk(GpioLineBulk lineBulk, GpioLineRequest lineRequest, int[] defaultVals) {
+ if(c_gpiod_line_request_bulk(lineBulk.getCPointer(), lineRequest.getCPointer(), defaultVals) < 0) {
+ throw new GpioDException("c_gpiod_line_request_bulk failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_bulk(long lineBulkPtr, long lineRequestPtr, int[] default_vals);
+
+ static void lineRequestBulkInput(GpioLineBulk lineBulk, String consumer) {
+ if(c_gpiod_line_request_bulk_input(lineBulk.getCPointer(), consumer) < 0) {
+ throw new GpioDException("c_gpiod_line_request_bulk_input failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_bulk_input(long lineBulkPtr, String consumer);
+
+ static void lineRequestBulkOutput(GpioLineBulk lineBulk, String consumer, int[] defaultVals) {
+ if(c_gpiod_line_request_bulk_output(lineBulk.getCPointer(), consumer, defaultVals) < 0) {
+ throw new GpioDException("c_gpiod_line_request_bulk_output failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_bulk_output(long lineBulkPtr, String consumer, int[] default_vals);
+
+ static void lineRequestBulkRisingEdgeEvents(GpioLineBulk lineBulk, String consumer) {
+ if(c_gpiod_line_request_bulk_rising_edge_events(lineBulk.getCPointer(), consumer) < 0) {
+ throw new GpioDException("c_gpiod_line_request_bulk_rising_edge_events failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_bulk_rising_edge_events(long lineBulkPtr, String consumer);
+
+ static void lineRequestBulkFallingEdgeEvents(GpioLineBulk lineBulk, String consumer) {
+ if(c_gpiod_line_request_bulk_falling_edge_events(lineBulk.getCPointer(), consumer) < 0) {
+ throw new GpioDException("c_gpiod_line_request_bulk_falling_edge_events failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_bulk_falling_edge_events(long lineBulkPtr, String consumer);
+
+ static void lineRequestBulkBothEdgeEvents(GpioLineBulk lineBulk, String consumer) {
+ if(c_gpiod_line_request_bulk_both_edges_events(lineBulk.getCPointer(), consumer) < 0) {
+ throw new GpioDException("c_gpiod_line_request_bulk_both_edges_events failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_bulk_both_edges_events(long lineBulkPtr, String consumer);
+
+ static void lineRequestBulkInputFlags(GpioLineBulk lineBulk, String consumer, int flags) {
+ if(c_gpiod_line_request_bulk_input_flags(lineBulk.getCPointer(), consumer, flags) < 0) {
+ throw new GpioDException("c_gpiod_line_request_bulk_input_flags failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_bulk_input_flags(long lineBulkPtr, String consumer, int flags);
+
+ static void lineRequestBulkOutputFlags(GpioLineBulk lineBulk, String consumer, int flags, int[] defaultVals) {
+ if(c_gpiod_line_request_bulk_output_flags(lineBulk.getCPointer(), consumer, flags, defaultVals) < 0) {
+ throw new GpioDException("c_gpiod_line_request_bulk_output_flags failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_bulk_output_flags(long lineBulkPtr, String consumer, int flags, int[] default_vals);
+
+ static void lineRequestBulkRisingEdgeEventFlags(GpioLineBulk lineBulk, String consumer, int flags) {
+ if(c_gpiod_line_request_bulk_rising_edge_events_flags(lineBulk.getCPointer(), consumer, flags) < 0) {
+ throw new GpioDException("c_gpiod_line_request_bulk_rising_edge_events_flags failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_bulk_rising_edge_events_flags(long lineBulkPtr, String consumer, int flags);
+
+ static void lineRequestBulkFallingEdgeEventFlags(GpioLineBulk lineBulk, String consumer, int flags) {
+ if(c_gpiod_line_request_bulk_falling_edge_events_flags(lineBulk.getCPointer(), consumer, flags) < 0) {
+ throw new GpioDException("c_gpiod_line_request_bulk_falling_edge_events_flags failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_bulk_falling_edge_events_flags(long lineBulkPtr, String consumer, int flags);
+
+ static void lineRequestBulkBothEdgeEventFlags(GpioLineBulk lineBulk, String consumer, int flags) {
+ if(c_gpiod_line_request_bulk_both_edges_events_flags(lineBulk.getCPointer(), consumer, flags) < 0) {
+ throw new GpioDException("c_gpiod_line_request_bulk_both_edges_events_flags failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_request_bulk_both_edges_events_flags(long lineBulkPtr, String consumer, int flags);
+
+ static void lineRelease(GpioLine line) {
+ c_gpiod_line_release(line.getCPointer());
+ }
+
+ private static native void c_gpiod_line_release(long linePtr);
+
+ static void lineBulkRelease(GpioLineBulk lineBulk) {
+ c_gpiod_line_release_bulk(lineBulk.getCPointer());
+ }
+
+ private static native void c_gpiod_line_release_bulk(long lineBulkPtr);
+
+ static boolean lineIsRequested(GpioLine line) {
+ return c_gpiod_line_is_requested(line.getCPointer());
+ }
+
+ private static native boolean c_gpiod_line_is_requested(long linePtr);
+
+ static boolean lineIsFree(GpioLine line) {
+ return c_gpiod_line_is_free(line.getCPointer());
+ }
+
+ private static native boolean c_gpiod_line_is_free(long linePtr);
+
+ static int lineGetValue(GpioLine line) {
+ int result = c_gpiod_line_get_value(line.getCPointer());
+ if(result < 0) {
+ throw new GpioDException("c_gpiod_line_get_value failed!");
+ }
+ return result;
+ }
+
+ private static native int c_gpiod_line_get_value(long linePtr);
+
+ static int[] lineBulkGetValues(GpioLineBulk lineBulk) {
+ int numVals = lineBulkGetNumLines(lineBulk);
+ int[] vals = new int[numVals];
+ if(c_gpiod_line_get_value_bulk(lineBulk.getCPointer(), vals) < 0) {
+ throw new GpioDException("c_gpiod_line_get_value_bulk failed!");
+ }
+ return vals;
+ }
+
+ private static native int c_gpiod_line_get_value_bulk(long lineBulkPtr, int[] values);
+
+ static void lineSetValue(GpioLine line, int value) {
+ if(c_gpiod_line_set_value(line.getCPointer(), value) < 0) {
+ throw new GpioDException("c_gpiod_line_set_value failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_set_value(long linePtr, int value);
+
+ static void lineBulkSetValue(GpioLineBulk lineBulk, int[] values) {
+ if(c_gpiod_line_set_value_bulk(lineBulk.getCPointer(), values) < 0) {
+ throw new GpioDException("c_gpiod_line_set_value_bulk failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_set_value_bulk(long lineBulkPtr, int[] values);
+
+ static void lineSetConfig(GpioLine line, LINE_REQUEST direction, int flags, int value) {
+ if(c_gpiod_line_set_config(line.getCPointer(), direction.val, flags, value) < 0) {
+ throw new GpioDException("c_gpiod_line_set_config failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_set_config(long linePtr, int direction, int flags, int value);
+
+ static void lineBulkSetConfig(GpioLineBulk lineBulk, LINE_REQUEST direction, int flags, int[] values) {
+ if(c_gpiod_line_set_config_bulk(lineBulk.getCPointer(), direction.val, flags, values) < 0) {
+ throw new GpioDException("c_gpiod_line_set_config_bulk failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_set_config_bulk(long lineBulkPtr, int direction, int flags, int[] values);
+
+ static void lineSetFlags(GpioLine line, int flags) {
+ if(c_gpiod_line_set_flags(line.getCPointer(), flags) < 0) {
+ throw new GpioDException("c_gpiod_line_set_flags failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_set_flags(long linePtr, int flags);
+
+ static void lineBulkSetFlags(GpioLineBulk lineBulk, int flags) {
+ if(c_gpiod_line_set_flags_bulk(lineBulk.getCPointer(), flags) < 0) {
+ throw new GpioDException("c_gpiod_line_set_flags_bulk failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_set_flags_bulk(long lineBulkPtr, int flags);
+
+ static void lineSetDirectionInput(GpioLine line) {
+ if(c_gpiod_line_set_direction_input(line.getCPointer()) < 0) {
+ throw new GpioDException("c_gpiod_line_set_direction_input failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_set_direction_input(long linePtr);
+
+ static void lineSetDirectionOutputBulk(GpioLineBulk lineBulk) {
+ if(c_gpiod_line_set_direction_input_bulk(lineBulk.getCPointer()) < 0) {
+ throw new GpioDException("c_gpiod_line_set_direction_input_bulk failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_set_direction_input_bulk(long lineBulkPtr);
+
+ static void lineSetDirectionOutput(GpioLine line, int value) {
+ if(c_gpiod_line_set_direction_output(line.getCPointer(), value) < 0) {
+ throw new GpioDException("c_gpiod_line_set_direction_output failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_set_direction_output(long linePtr, int value);
+
+ static void lineSetDirectionOutputBulk(GpioLineBulk lineBulk, int[] values) {
+ if(c_gpiod_line_set_direction_output_bulk(lineBulk.getCPointer(), values) < 0) {
+ throw new GpioDException("c_gpiod_line_set_direction_output_bulk failed!");
+ }
+ }
+
+ private static native int c_gpiod_line_set_direction_output_bulk(long lineBulkPtr, int[] values);
+
+ public enum LINE_EVENT {
+ RISING_EDGE(1), FALLING_EDGE(2);
+ final int val;
+
+ public int getVal() {
+ return val;
+ }
+
+ LINE_EVENT(int val) {
+ this.val = val;
+ }
+
+ static LINE_EVENT fromInt(int val) {
+ for (LINE_EVENT dir : LINE_EVENT.values()) {
+ if (dir.val == val) {
+ return dir;
+ }
+ }
+ throw new IllegalStateException("Unexpected LINE_EVENT value: " + val);
+ }
+ }
+
+ static boolean lineEventWait(GpioLine line, long timeoutNs) {
+ int result = c_gpiod_line_event_wait(line.getCPointer(), timeoutNs);
+ if(result < 0) {
+ throw new GpioDException("c_gpiod_line_event_wait failed!");
+ }
+ return result > 0;
+ }
+
+ private static native int c_gpiod_line_event_wait(long linePtr, long timeoutNs);
+
+ static boolean lineBulkEventWait(GpioLineBulk lineBulk, long timeoutNs, GpioLineBulk eventBulk) {
+ int result = c_gpiod_line_event_wait_bulk(lineBulk.getCPointer(), timeoutNs, eventBulk.getCPointer());
+ if(result < 0) {
+ throw new GpioDException("c_gpiod_line_event_wait_bulk failed!");
+ }
+ return result > 0;
+ }
+
+ private static native int c_gpiod_line_event_wait_bulk(long lineBulkPtr, long timeoutNs, long eventBulkPtr);
+
+ static boolean lineEventRead(GpioLine line, GpioLineEvent event) {
+ int result = c_gpiod_line_event_read(line.getCPointer(), event.getCPointer());
+ if(result < 0) {
+ throw new GpioDException("c_gpiod_line_event_read failed!");
+ }
+ return result > 0;
+ }
+
+ private static native int c_gpiod_line_event_read(long linePtr, long eventPtr);
+
+ static GpioLineEvent[] lineEventReadMultiple(GpioLine line, int maxRead) {
+ GpioLineEvent[] events = new GpioLineEvent[maxRead];
+ for(int i = 0; i < events.length; i++) {
+ events[i] = new GpioLineEvent();
+ }
+
+ int numRead = c_gpiod_line_event_read_multiple(line.getCPointer(),
+ Arrays.stream(events).mapToLong(GpioLineEvent::getCPointer).toArray(), events.length);
+ if(numRead < 0) {
+ throw new GpioDException("c_gpiod_line_event_read_multiple failed!");
+ }
+
+ GpioLineEvent[] result = new GpioLineEvent[numRead];
+ if(numRead == maxRead) {
+ result = events;
+ } else {
+ System.arraycopy(events, 0, result, 0, result.length);
+ }
+ return result;
+ }
+
+ private static native int c_gpiod_line_event_read_multiple(long linePtr, long[] eventPtr, int num_events);
+
+ static GpioLine lineGet(String device, int offset) {
+ Long ptr = c_gpiod_line_get(device, offset);
+ if(ptr == null) {
+ throw new GpioDException("c_gpiod_line_get failed!");
+ }
+ return new GpioLine(ptr);
+ }
+
+ private static native Long c_gpiod_line_get(String device, int offset);
+
+ static GpioLine lineFind(String name) {
+ Long ptr = gpiod_line_find(name);
+ if(ptr == null) {
+ throw new GpioDException("gpiod_line_find failed!");
+ }
+ return new GpioLine(ptr);
+ }
+
+ private static native Long gpiod_line_find(String name);
+
+ static void lineCloseChip(GpioLine line) {
+ c_gpiod_line_close_chip(line.getCPointer());
+ }
+
+ private static native void c_gpiod_line_close_chip(long linePtr);
+
+ static GpioChip lineGetChip(GpioLine line) {
+ return new GpioChip(gpiod_line_get_chip(line.getCPointer()));
+ }
+
+ private static native long gpiod_line_get_chip(long linePtr);
+
+ static long chipIterNew() {
+ Long ptr = gpiod_chip_iter_new();
+ if(ptr == null) {
+ throw new GpioDException("gpiod_chip_iter_new failed!");
+ }
+ return ptr;
+ }
+
+ private static native Long gpiod_chip_iter_new();
+
+ static void chipIterFree(GpioChipIterator iter) {
+ c_gpiod_chip_iter_free(iter.getCPointer());
+ }
+
+ private static native void c_gpiod_chip_iter_free(long chipIterPtr);
+
+ static void chipIterFreeNoClose(GpioChipIterator iter) {
+ c_gpiod_chip_iter_free_noclose(iter.getCPointer());
+ }
+
+ private static native void c_gpiod_chip_iter_free_noclose(long chipIterPtr);
+
+ static GpioChip chipIterNext(GpioChipIterator iter) {
+ Long ptr = c_gpiod_chip_iter_next(iter.getCPointer());
+ if(ptr == null) {
+ return null;
+ }
+ return new GpioChip(ptr);
+ }
+
+ private static native Long c_gpiod_chip_iter_next(long chipIterPtr);
+
+ static GpioChip chipIterNextNoClose(GpioChipIterator iter) {
+ Long ptr = c_gpiod_chip_iter_next_noclose(iter.getCPointer());
+ if(ptr == null) {
+ return null;
+ }
+ return new GpioChip(ptr);
+ }
+
+ private static native Long c_gpiod_chip_iter_next_noclose(long chipIterPtr);
+
+ static long lineIterNew(GpioChip chip) {
+ Long ptr = gpiod_line_iter_new(chip.getCPointer());
+ if(ptr == null) {
+ throw new GpioDException("gpiod_line_iter_new failed!");
+ }
+ return ptr;
+ }
+
+ private static native Long gpiod_line_iter_new(long chipPtr);
+
+ static void lineIterFree(GpioLineIterator iter) {
+ gpiod_line_iter_free(iter.getCPointer());
+ }
+
+ private static native void gpiod_line_iter_free(long lineIterPtr);
+
+ static GpioLine lineIterNext(GpioLineIterator iter) {
+ Long ptr = gpiod_line_iter_next(iter.getCPointer());
+ if(ptr == null) {
+ return null;
+ }
+ return new GpioLine(ptr);
+ }
+
+ private static native Long gpiod_line_iter_next(long lineIterPtr);
+
+ static long lineEventGetTimespec(GpioLineEvent event) {
+ return c_gpiod_line_event_get_timespec(event.getCPointer());
+ }
+
+ private static native long c_gpiod_line_event_get_timespec(long lineEventPtr);
+
+ static LINE_EVENT lineEventGetType(GpioLineEvent event) {
+ return LINE_EVENT.fromInt(c_gpiod_line_event_get_type(event.getCPointer()));
+ }
+
+ private static native int c_gpiod_line_event_get_type(long lineEventPtr);
+
+ static long lineEventNew() {
+ Long ptr = c_gpiod_line_event_new();
+ if(ptr == null) {
+ throw new GpioDException("c_gpiod_line_event_new failed!");
+ }
+ return ptr;
+ }
+
+ private static native Long c_gpiod_line_event_new();
+
+ static void lineEventFree(GpioLineEvent event) {
+ c_gpiod_line_event_free(event.getCPointer());
+ }
+
+ private static native void c_gpiod_line_event_free(long eventPtr);
+
+ static String getVersion() {
+ return c_gpiod_version_string();
+ }
+
+ private static native String c_gpiod_version_string();
+
+}
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioDException.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioDException.java
new file mode 100644
index 00000000..849811b6
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioDException.java
@@ -0,0 +1,17 @@
+package com.pi4j.library.gpiod.internal;
+
+/**
+ * GpioDException
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioDException extends RuntimeException {
+ public GpioDException() {
+ super();
+ }
+
+ public GpioDException(String msg) {
+ super(msg);
+ }
+}
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLine.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLine.java
new file mode 100644
index 00000000..f50a6176
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLine.java
@@ -0,0 +1,151 @@
+package com.pi4j.library.gpiod.internal;
+
+import java.util.Objects;
+
+/**
+ * GpioLine
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioLine extends CWrapper {
+
+ GpioLine(long cPointer) {
+ super(cPointer);
+ }
+
+ public int getOffset() {
+ return GpioD.lineGetOffset(this);
+ }
+
+ public String getName() {
+ return GpioD.lineGetName(this);
+ }
+
+ public String getConsumer() {
+ return GpioD.lineGetConsumer(this);
+ }
+
+ public GpioD.LINE_DIRECTION getDirection() {
+ return GpioD.lineGetDirection(this);
+ }
+
+ public GpioD.LINE_ACTIVE_STATE getActiveState() {
+ return GpioD.lineGetActiveState(this);
+ }
+
+ public GpioD.LINE_BIAS getBias() {
+ return GpioD.lineGetBias(this);
+ }
+
+ public boolean isUsed() {
+ return GpioD.lineIsUsed(this);
+ }
+
+ public boolean isOpenDrain() {
+ return GpioD.lineIsOpenDrain(this);
+ }
+
+ public boolean isOpenSource() {
+ return GpioD.lineIsOpenSource(this);
+ }
+
+ public void update() {
+ GpioD.lineUpdate(this);
+ }
+
+ public void request(GpioLineRequest config, int defaultVal) {
+ GpioD.lineRequest(this, config, defaultVal);
+ }
+
+ public void requestInput(String consumer) {
+ GpioD.lineRequestInput(this, consumer);
+ }
+
+ public void requestOutput(String consumer, int defaultVal) {
+ GpioD.lineRequestOutput(this, consumer, defaultVal);
+ }
+
+ public void requestRisingEdgeEvents(String consumer) {
+ GpioD.lineRequestRisingEdgeEvents(this, consumer);
+ }
+
+ public void requestFallingEdgeEvents(String consumer) {
+ GpioD.lineRequestFallingEdgeEvents(this, consumer);
+ }
+
+ public void requestBothEdgeEvents(String consumer) {
+ GpioD.lineRequestBothEdgeEvents(this, consumer);
+ }
+
+ public void requestInputFlags(String consumer, int flags) {
+ GpioD.lineRequestInputFlags(this, consumer, flags);
+ }
+
+ public void requestOutputFlags(String consumer, int flags, int defaultValue) {
+ GpioD.lineRequestOutputFlags(this, consumer, flags, defaultValue);
+ }
+
+ public void requestRisingEdgeEventsFlags(String consumer, int flags) {
+ GpioD.lineRequestRisingEdgeEventsFlags(this, consumer, flags);
+ }
+
+ public void requestFallingEdgeEventsFlags(String consumer, int flags) {
+ GpioD.lineRequestFallingEdgeEventsFlags(this, consumer, flags);
+ }
+
+ public void requestBothEdgeEventsFlags(String consumer, int flags) {
+ GpioD.lineRequestBothEdgeEventsFlags(this, consumer, flags);
+ }
+
+ public void release() {
+ GpioD.lineRelease(this);
+ }
+
+ public boolean isRequested() {
+ return GpioD.lineIsRequested(this);
+ }
+
+ public boolean isFree() {
+ return GpioD.lineIsFree(this);
+ }
+
+ public int getValue() {
+ return GpioD.lineGetValue(this);
+ }
+
+ public void setValue(int value) {
+ GpioD.lineSetValue(this, value);
+ }
+
+ public void setConfig(GpioD.LINE_REQUEST direction, int flags, int value) {
+ GpioD.lineSetConfig(this, direction, flags, value);
+ }
+
+ public void setFlags(int flags) {
+ GpioD.lineSetFlags(this, flags);
+ }
+
+ public void setDirectionInput() {
+ GpioD.lineSetDirectionInput(this);
+ }
+
+ public void setDirectionOutput(int value) {
+ GpioD.lineSetDirectionOutput(this, value);
+ }
+
+ public boolean eventWait(long timeoutNs) {
+ return GpioD.lineEventWait(this, timeoutNs);
+ }
+
+ public GpioLineEvent eventRead() {
+ GpioLineEvent event = new GpioLineEvent();
+ GpioD.lineEventRead(this, event);
+ return event;
+ }
+
+ public GpioLineEvent[] eventReadMultiple(int maxRead) {
+ return GpioD.lineEventReadMultiple(this, maxRead);
+ }
+
+}
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineBulk.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineBulk.java
new file mode 100644
index 00000000..21cf0840
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineBulk.java
@@ -0,0 +1,114 @@
+package com.pi4j.library.gpiod.internal;
+
+/**
+ * GpioLineBulk
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioLineBulk extends CWrapper {
+
+ GpioLineBulk(long cPointer) {
+ super(cPointer);
+ }
+
+ public GpioLineBulk() {
+ this(GpioD.lineBulkNew());
+ }
+
+ @Override
+ protected void finalize() {
+ GpioD.lineBulkFree(this);
+ }
+
+ public void add(GpioLine line) {
+ GpioD.lineBulkAdd(this, line);
+ }
+
+ public GpioLine getLine(int index) {
+ return GpioD.lineBulkGetLine(this, index);
+ }
+
+ public int getNumLines() {
+ return GpioD.lineBulkGetNumLines(this);
+ }
+
+ public void request(GpioLineRequest config, int[] defaultVals) {
+ GpioD.lineRequestBulk(this, config, defaultVals);
+ }
+
+ public void requestInput(String consumer) {
+ GpioD.lineRequestBulkInput(this, consumer);
+ }
+
+ public void requestOutput(String consumer, int[] defaultVals) {
+ GpioD.lineRequestBulkOutput(this, consumer, defaultVals);
+ }
+
+ public void requestRisingEdgeEvents(String consumer) {
+ GpioD.lineRequestBulkRisingEdgeEvents(this, consumer);
+ }
+
+ public void requestFallingEdgeEvents(String consumer) {
+ GpioD.lineRequestBulkFallingEdgeEvents(this, consumer);
+ }
+
+ public void requestBothEdgeEvents(String consumer) {
+ GpioD.lineRequestBulkBothEdgeEvents(this, consumer);
+ }
+
+ public void requestInputFlags(String consumer, int flags) {
+ GpioD.lineRequestBulkInputFlags(this, consumer, flags);
+ }
+
+ public void requestOutputFlags(String consumer, int flags, int[] defaultValue) {
+ GpioD.lineRequestBulkOutputFlags(this, consumer, flags, defaultValue);
+ }
+
+ public void requestRisingEdgeEventsFlags(String consumer, int flags) {
+ GpioD.lineRequestBulkRisingEdgeEventFlags(this, consumer, flags);
+ }
+
+ public void requestFallingEdgeEventsFlags(String consumer, int flags) {
+ GpioD.lineRequestBulkFallingEdgeEventFlags(this, consumer, flags);
+ }
+
+ public void requestBothEdgeEventsFlags(String consumer, int flags) {
+ GpioD.lineRequestBulkBothEdgeEventFlags(this, consumer, flags);
+ }
+
+ public void release() {
+ GpioD.lineBulkRelease(this);
+ }
+
+ public int[] getValues() {
+ return GpioD.lineBulkGetValues(this);
+ }
+
+ public void setValue(int[] values) {
+ GpioD.lineBulkSetValue(this, values);
+ }
+
+ public void setConfig(GpioD.LINE_REQUEST direction, int flags, int[] values) {
+ GpioD.lineBulkSetConfig(this, direction, flags, values);
+ }
+
+ public void setFlags(int flags) {
+ GpioD.lineBulkSetFlags(this, flags);
+ }
+
+ public void setDirectionInput() {
+ GpioD.lineSetDirectionOutputBulk(this);
+ }
+
+ public void setDirectionOutput(int[] values) {
+ GpioD.lineSetDirectionOutputBulk(this, values);
+ }
+
+ public GpioLineBulk eventWait(long timeoutNs) {
+ GpioLineBulk bulk = new GpioLineBulk();
+ GpioD.lineBulkEventWait(this, timeoutNs, bulk);
+ return bulk;
+ }
+
+}
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineEvent.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineEvent.java
new file mode 100644
index 00000000..29a617e8
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineEvent.java
@@ -0,0 +1,31 @@
+package com.pi4j.library.gpiod.internal;
+
+/**
+ * GpioLineEvent
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioLineEvent extends CWrapper {
+
+ GpioLineEvent(long cPointer) {
+ super(cPointer);
+ }
+
+ public GpioLineEvent() {
+ this(GpioD.lineEventNew());
+ }
+
+ @Override
+ protected void finalize() {
+ GpioD.lineEventFree(this);
+ }
+
+ public long getTimeNs() {
+ return GpioD.lineEventGetTimespec(this);
+ }
+
+ public GpioD.LINE_EVENT getType() {
+ return GpioD.lineEventGetType(this);
+ }
+}
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineIterator.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineIterator.java
new file mode 100644
index 00000000..9b216bf2
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineIterator.java
@@ -0,0 +1,41 @@
+package com.pi4j.library.gpiod.internal;
+
+import java.util.Iterator;
+
+/**
+ * GpioLineIterator
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioLineIterator extends CWrapper implements Iterator {
+
+ private GpioLine next;
+
+ GpioLineIterator(long cPointer) {
+ super(cPointer);
+ }
+
+ public GpioLineIterator(GpioChip chip) {
+ this(GpioD.lineIterNew(chip));
+ }
+
+ @Override
+ public boolean hasNext() {
+ if(next == null) {
+ next = GpioD.lineIterNext(this);
+ }
+ return next != null;
+ }
+
+ @Override
+ public GpioLine next() {
+ GpioLine current;
+ if(next == null) {
+ next = GpioD.lineIterNext(this);
+ }
+ current = next;
+ next = null;
+ return current;
+ }
+}
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineRequest.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineRequest.java
new file mode 100644
index 00000000..52ba3a4e
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/internal/GpioLineRequest.java
@@ -0,0 +1,15 @@
+package com.pi4j.library.gpiod.internal;
+
+/**
+ * GpioLineRequest
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioLineRequest extends CWrapper {
+
+ GpioLineRequest(long cPointer) {
+ super(cPointer);
+ }
+
+}
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/util/NativeLibraryLoader.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/util/NativeLibraryLoader.java
new file mode 100644
index 00000000..24ac868e
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/util/NativeLibraryLoader.java
@@ -0,0 +1,258 @@
+package com.pi4j.library.gpiod.util;
+/*
+ * #%L
+ * **********************************************************************
+ * ORGANIZATION : Pi4J
+ * PROJECT : Pi4J :: LIBRARY :: JNI Wrapper for LinuxFS Library
+ * FILENAME : NativeLibraryLoader.java
+ *
+ * This file is part of the Pi4J project. More information about
+ * this project can be found here: https://pi4j.com/
+ * **********************************************************************
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.Set;
+import java.util.TreeSet;
+
+public class NativeLibraryLoader {
+
+ private static final Set loadedLibraries = new TreeSet<>();
+ protected static final Logger logger = LoggerFactory.getLogger(NativeLibraryLoader.class);
+ private static boolean initialized;
+
+ // private constructor
+ private NativeLibraryLoader() {
+ // forbid object construction
+ }
+
+ public static synchronized void load(String fileName, String libName) {
+ // check for debug property; if found enable all logging levels
+ if (!initialized) {
+ initialized = true;
+ }
+
+ // first, make sure that this library has not already been previously loaded
+ if (loadedLibraries.contains(fileName)) {
+ logger.warn("Library [" + fileName + "] has already been loaded; no need to load again.");
+ return;
+ }
+
+ // cache loaded library
+ loadedLibraries.add(fileName);
+
+ // determine if there is an overriding library path defined for native libraries
+ String libpath = System.getProperty("pi4j.library.path");
+ if(StringUtil.isNotNullOrEmpty(libpath, true)) {
+
+ // if the overriding library path is set to "system", then attempt to use the system resolved library paths
+ if (libpath.equalsIgnoreCase("system")) {
+ logger.debug("Attempting to load library using {pi4j.library.path} system resolved library name: [" + libName + "]");
+ try {
+ // load library from JVM system library path; based on library name
+ System.loadLibrary(libName);
+ }
+ catch (Exception ex){
+ //throw this error
+ throw new UnsatisfiedLinkError("Pi4J was unable load the native library [" +
+ libName + "] from the system defined library path. The system property 'pi4j.library.path' is defined as [" +
+ libpath + "]. You can alternatively define the 'pi4j.library.path' " +
+ "system property to override this behavior and specify an absolute library path." +
+ "; UNDERLYING EXCEPTION: [" + ex.getClass().getName() + "]=" + ex.getMessage());
+ }
+ }
+
+ // if the overriding library path is set to "local", then attempt to use the JAR local path to resolve library
+ else if (libpath.equalsIgnoreCase("local")) {
+ // get local directory path of JAR file
+ try {
+ libpath = NativeLibraryLoader.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath();
+ } catch (URISyntaxException e) {
+ logger.error(e.getMessage(), e);
+ libpath = ".";
+ }
+ // build path based on lib directory and lib filename
+ String path = Paths.get(libpath, fileName).toString();
+ logger.debug("Attempting to load library using {pi4j.library.path} defined path: [" + path + "]");
+ try {
+ // load library from local path of this JAR file
+ System.load(path);
+ }
+ catch (Exception ex){
+ //throw this error
+ throw new UnsatisfiedLinkError("Pi4J was unable load the native library [" +
+ libName + "] from the user defined library path. The system property 'pi4j.library.path' is defined as [" +
+ libpath + "]. Please make sure the defined the 'pi4j.library.path' " +
+ "system property contains the correct absolute library path." +
+ "; UNDERLYING EXCEPTION: [" + ex.getClass().getName() + "]=" + ex.getMessage());
+ }
+ }
+
+ // if the overriding library path is set to something else, then attempt to use the defined path to resolve library
+ else {
+ // build path based on lib directory and lib filename
+ String path = Paths.get(libpath, fileName).toString();
+ logger.debug("Attempting to load library using {pi4j.library.path} defined path: [" + path + "]");
+ try {
+ // load library from user defined absolute path provided via pi4j.library.path}
+ System.load(path);
+ } catch (UnsatisfiedLinkError ex) {
+ String exceptMessage;
+ // no guarantee the except pertains to ELF miss-match so check MSG content
+ if (ex.getMessage().contains("wrong ELF class")) {
+ exceptMessage = "Pi4J was unable to link the native library [" +
+ path + "] embedded inside this JAR [" +
+ NativeLibraryLoader.class.getProtectionDomain().getCodeSource().getLocation().getPath() +
+ "]. The exception indicates a mismatch of architecture. armhf/ELFCLASS32 aarch64/ELFCLASS64 \n" +
+ " UNDERLYING EXCEPTION: [" + ex.getClass().getName() + "]=" + ex.getMessage();
+ } else {
+ exceptMessage = "Pi4J was unable to extract and load the native library [" +
+ path + "] from the embedded resources inside this JAR [" +
+ NativeLibraryLoader.class.getProtectionDomain().getCodeSource().getLocation().getPath() +
+ "]. to a temporary location on this system. You can alternatively define the 'pi4j.library.path' " +
+ "system property to override this behavior and specify the library path.\n" +
+ " UNDERLYING EXCEPTION: [" + ex.getClass().getName() + "]=" + ex.getMessage();
+ }
+ throw new UnsatisfiedLinkError(exceptMessage);
+ } catch (Exception ex) {
+ throw new UnsatisfiedLinkError("Pi4J was unable to extract and load the native library [" +
+ path + "] from the embedded resources inside this JAR [" +
+ NativeLibraryLoader.class.getProtectionDomain().getCodeSource().getLocation().getPath() +
+ "]. to a temporary location on this system. You can alternatively define the 'pi4j.library.path' " +
+ "system property to override this behavior and specify the library path.\n" +
+ " UNDERLYING EXCEPTION: [" + ex.getClass().getName() + "]=" + ex.getMessage());
+ }
+ }
+ }
+
+ // if there is no overriding library path defined, then attempt to load native library from embedded resource
+ else {
+ // get CPU architecture from system properties
+ String osArch = System.getProperty("os.arch").toLowerCase();
+
+ // sanitize CPU architecture string
+ switch (osArch) {
+ case "arm":
+ osArch = "armhf";
+ break;
+ case "arm64":
+ osArch = "aarch64";
+ break;
+ case "aarch64":
+ break;
+ default:
+ throw new IllegalStateException("Pi4J has detected and UNKNOWN/UNSUPPORTED 'os.arch' : [" +
+ osArch + "]; only 'arm|armhf' and 'arm64|aarch64' are supported.");
+ }
+
+ // include the CPU architecture in the embedded path
+ String path = "/lib/" + osArch + "/" + libName + "/" + fileName;
+ logger.debug("Attempting to load library [" + fileName + "] using path: [" + path + "]");
+ try {
+ loadLibraryFromClasspath(path);
+ logger.debug("Library [" + fileName + "] loaded successfully using embedded resource file: [" + path + "]");
+ } catch (UnsatisfiedLinkError e) {
+ logger.error("Unable to load [" + fileName + "] using path: [" + path + "]", e);
+ String exceptMessage;
+ // no guarantee the except pertains to ELF miss-match so check MSG content
+ if (e.getMessage().contains("wrong ELF class")) {
+ exceptMessage = "Pi4J was unable to link the native library [" +
+ path + "] embedded inside this JAR [" +
+ NativeLibraryLoader.class.getProtectionDomain().getCodeSource().getLocation().getPath() +
+ "]. The exception indicates a mismatch of architecture. armhf/ELFCLASS32 aarch64/ELFCLASS64 \n" +
+ " All native libraries must be of architecture " + osArch + " \n" +
+ " UNDERLYING EXCEPTION: [" + e.getClass().getName() + "]=" + e.getMessage();
+ } else {
+ exceptMessage = "Pi4J was unable to extract and load the native library [" +
+ path + "] from the embedded resources inside this JAR [" +
+ NativeLibraryLoader.class.getProtectionDomain().getCodeSource().getLocation().getPath() +
+ "]. to a temporary location on this system. You can alternatively define the 'pi4j.library.path' " +
+ "system property to override this behavior and specify the library path.\n" +
+ " UNDERLYING EXCEPTION: [" + e.getClass().getName() + "]=" + e.getMessage();
+ }
+ throw new UnsatisfiedLinkError(exceptMessage);
+ } catch (Exception e) {
+ logger.error("Unable to load [" + fileName + "] using path: [" + path + "]", e);
+ throw new UnsatisfiedLinkError("Pi4J was unable to extract and load the native library [" +
+ path + "] from the embedded resources inside this JAR [" +
+ NativeLibraryLoader.class.getProtectionDomain().getCodeSource().getLocation().getPath() +
+ "]. to a temporary location on this system. You can alternatively define the 'pi4j.library.path' " +
+ "system property to override this behavior and specify the library path.\n" +
+ " UNDERLYING EXCEPTION: [" + e.getClass().getName() + "]=" + e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Loads library from classpath
+ *
+ * The file from classpath is copied into system temporary directory and then loaded. The temporary file is
+ * deleted after exiting. Method uses String as filename because the pathname is
+ * "abstract", not system-dependent.
+ *
+ * @param path
+ * The file path in classpath as an absolute path, e.g. /package/File.ext (could be inside jar)
+ * @throws IOException
+ * If temporary file creation or read/write operation fails
+ * @throws IllegalArgumentException
+ * If source file (param path) does not exist
+ * @throws IllegalArgumentException
+ * If the path is not absolute or if the filename is shorter than three characters (restriction
+ * of {@see File#createTempFile(java.lang.String, java.lang.String)}).
+ */
+ public static void loadLibraryFromClasspath(String path) throws IOException {
+ Path inputPath = Paths.get(path);
+
+ if (!inputPath.isAbsolute()) {
+ throw new IllegalArgumentException("The path has to be absolute, but found: " + inputPath);
+ }
+
+ String fileNameFull = inputPath.getFileName().toString();
+ int dotIndex = fileNameFull.indexOf('.');
+ if (dotIndex < 0 || dotIndex >= fileNameFull.length() - 1) {
+ throw new IllegalArgumentException("The path has to end with a file name and extension, but found: " + fileNameFull);
+ }
+
+ String fileName = fileNameFull.substring(0, dotIndex);
+ String extension = fileNameFull.substring(dotIndex);
+
+ Path target = Files.createTempFile(fileName, extension);
+ File targetFile = target.toFile();
+ targetFile.deleteOnExit();
+
+ try (InputStream source = NativeLibraryLoader.class.getResourceAsStream(inputPath.toString())) {
+ if (source == null) {
+ throw new FileNotFoundException("File " + inputPath + " was not found in classpath.");
+ }
+ Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
+ }
+ // Finally, load the library
+ System.load(target.toAbsolutePath().toString());
+ }
+}
\ No newline at end of file
diff --git a/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/util/StringUtil.java b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/util/StringUtil.java
new file mode 100644
index 00000000..b4c14097
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/com/pi4j/library/gpiod/util/StringUtil.java
@@ -0,0 +1,634 @@
+package com.pi4j.library.gpiod.util;
+/*
+ * #%L
+ * **********************************************************************
+ * ORGANIZATION : Pi4J
+ * PROJECT : Pi4J :: LIBRARY :: JNI Wrapper for LinuxFS Library
+ * FILENAME : StringUtil.java
+ *
+ * This file is part of the Pi4J project. More information about
+ * this project can be found here: https://pi4j.com/
+ * **********************************************************************
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+/**
+ * StringUtil class.
+ *
+ * @author Robert Savage (http://www.savagehomeautomation.com )
+ * @version $Id: $Id
+ */
+public class StringUtil {
+
+ /** Constant 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();
+ }
+
+}
\ No newline at end of file
diff --git a/libraries/pi4j-library-gpiod/src/main/java/module-info.java b/libraries/pi4j-library-gpiod/src/main/java/module-info.java
new file mode 100644
index 00000000..8dde242c
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/java/module-info.java
@@ -0,0 +1,38 @@
+/*-
+ * #%L
+ * **********************************************************************
+ * ORGANIZATION : Pi4J
+ * PROJECT : Pi4J :: LIBRARY :: JNI Wrapper for LinuxFS Library
+ * FILENAME : module-info.java
+ *
+ * This file is part of the Pi4J project. More information about
+ * this project can be found here: https://pi4j.com/
+ * **********************************************************************
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+module com.pi4j.library.gpiod {
+
+ // SLF4J
+ requires org.slf4j;
+
+ // PI4J
+ requires com.pi4j;
+
+
+ // EXPORTS
+ exports com.pi4j.library.gpiod.internal;
+}
diff --git a/libraries/pi4j-library-gpiod/src/main/native/Makefile b/libraries/pi4j-library-gpiod/src/main/native/Makefile
new file mode 100644
index 00000000..537b8b67
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/native/Makefile
@@ -0,0 +1,70 @@
+#
+# Makefile:
+# pi4j-gpiod - Pi4J Java (JNI) library wrapper for gpiod
+#
+
+#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 \
+ -I/usr/include -I./gpiod/install/include
+
+CFLAGS := $(DEBUG) -Wall $(INCLUDE) -Winline -pipe $(CARGS) -fPIC
+LIBS = -L lib/$(ARCH)/pi4j-gpiod -L gpiod -lgpiod -lrt
+
+TARGET=libpi4j-gpiod.so
+
+# Should not alter anything below this line
+###############################################################################
+
+SRC = com_pi4j_library_gpiod_internal_GpioD.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_gpiod_internal_GpioD.o: com_pi4j_library_gpiod_internal_GpioD.h
diff --git a/libraries/pi4j-library-gpiod/src/main/native/build-docker.sh b/libraries/pi4j-library-gpiod/src/main/native/build-docker.sh
new file mode 100755
index 00000000..6bd057fd
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/native/build-docker.sh
@@ -0,0 +1,59 @@
+#!/bin/bash -e
+###
+# #%L
+# **********************************************************************
+# ORGANIZATION : Pi4J
+# PROJECT : Pi4J :: JNI Native Binding Library for GpioD
+# 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-gpiod/src/main/native/build-libgpiod.sh b/libraries/pi4j-library-gpiod/src/main/native/build-libgpiod.sh
new file mode 100755
index 00000000..050d57eb
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/native/build-libgpiod.sh
@@ -0,0 +1,77 @@
+#!/bin/bash -e
+###
+# #%L
+# **********************************************************************
+# ORGANIZATION : Pi4J
+# PROJECT : Pi4J :: JNI Native Binding Library for GPIOD
+# FILENAME : build-libpigpio.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%
+###
+
+# -- RASPBERRY PI --
+# set default GPIOD repository URL if not already defined
+if [ -z $GPIOD_REPO ]; then
+ GPIOD_REPO=https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git
+fi
+# set default GPIOD repository branch if not already defined
+if [ -z $GPIOD_BRANCH ]; then
+ GPIOD_BRANCH=v1.6.x
+fi
+# set default GPIOD directory if not already defined
+if [ -z $GPIOD_DIRECTORY ]; then
+ GPIOD_DIRECTORY=gpiod
+fi
+
+echo "====================================="
+echo "BUILDING: ${ARCH}/libgpiod"
+echo "====================================="
+echo "REPOSITORY : $GPIOD_REPO"
+echo "BRANCH : $GPIOD_BRANCH"
+echo "DIRECTORY : $GPIOD_DIRECTORY"
+echo "HOST ARCHITECTURE: ${HOST}"
+
+# ----------------------------------
+# clone GPIOD from github
+# ----------------------------------
+rm -rf $GPIOD_DIRECTORY
+git clone $GPIOD_REPO -b $GPIOD_BRANCH $GPIOD_DIRECTORY --single-branch --depth 1
+
+#rm -f pigpio.tar
+#wget abyz.me.uk/rpi/pigpio/pigpio.tar
+#tar xf pigpio.tar
+
+# ----------------------------------
+# build latest GPIOD
+# ----------------------------------
+cd $GPIOD_DIRECTORY
+
+./autogen.sh --enable-tools=no --prefix=$(pwd)/install --host=${HOST}
+
+make clean all install \
+ CROSS_PREFIX=${CROSS_PREFIX} \
+ CC=$CC \
+ ARCH=$ARCH
+
+#echo "Copying GPIOD library files to parent 'lib' folder"
+mkdir -p ../lib/${ARCH}/pi4j-gpiod
+cp install/lib/libgpiod.so ../lib/${ARCH}/pi4j-gpiod/libgpiod.so
diff --git a/libraries/pi4j-library-gpiod/src/main/native/build-libpi4j.sh b/libraries/pi4j-library-gpiod/src/main/native/build-libpi4j.sh
new file mode 100755
index 00000000..d2be09a0
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/native/build-libpi4j.sh
@@ -0,0 +1,68 @@
+#!/bin/bash -e
+###
+# #%L
+# **********************************************************************
+# ORGANIZATION : Pi4J
+# PROJECT : Pi4J :: JNI Native Binding Library for PIGPIO
+# 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 PiGPIO JNI Wrapper Library
+# ----------------------------------------------
+
+echo
+echo "============================================================================="
+echo " STARTED BUILDING Pi4J-PIGPIO JNI NATIVE LIBRARY: ('${ARCH}/pi4j-gpiod/libpi4j-gpiod')"
+echo "============================================================================="
+echo " - FOR ARCHITECTURE : ${ARCH}"
+echo " - USING COMPILER : ${CC}"
+echo " - USING CROSS PREFIX : ${CROSS_PREFIX}"
+echo "-----------------------------------------------------------------------------"
+echo
+
+./build-libgpiod.sh $@
+
+# ------------------------------------------------------
+# BUILD LIBPI4J-GPIOD
+# ------------------------------------------------------
+echo
+echo "====================================="
+echo "BUILDING: ${ARCH}/pi4j-gpiod/libpi4j-gpiod"
+echo "====================================="
+
+# perform compile
+mkdir -p lib/${ARCH}/pi4j-gpiod
+make clean all \
+ --always-make \
+ CROSS_PREFIX=${CROSS_PREFIX} \
+ CC=${CC} \
+ ARCH=${ARCH} \
+ TARGET=lib/${ARCH}/pi4j-gpiod/libpi4j-gpiod.so $@
+
+echo
+echo "-----------------------------------------------------------------------------"
+echo " FINISHED BUILDING Pi4J-PIGPIO JNI NATIVE LIBRARY: ('${ARCH}/libpi4j-gpiod')"
+echo "-----------------------------------------------------------------------------"
+echo
\ No newline at end of file
diff --git a/libraries/pi4j-library-gpiod/src/main/native/build-prerequisites.sh b/libraries/pi4j-library-gpiod/src/main/native/build-prerequisites.sh
new file mode 100755
index 00000000..6f104c88
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/native/build-prerequisites.sh
@@ -0,0 +1,139 @@
+#!/bin/bash
+###
+# #%L
+# **********************************************************************
+# ORGANIZATION : Pi4J
+# PROJECT : Pi4J :: JNI Native Binding Library for PIGPIO
+# 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
+
+ # GCC
+ GCC_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' gcc|grep "install ok installed")
+ if [[ "" == "$GCC_INSTALLED" ]]; then
+ sudo apt-get --force-yes --yes install gcc
+ else
+ echo " [PREREQUISITE] 'gcc' already installed.";
+ fi
+
+ # GIT
+ GIT_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' git|grep "install ok installed")
+ if [[ "" == "$GIT_INSTALLED" ]]; then
+ sudo apt-get --force-yes --yes install git
+ else
+ echo " [PREREQUISITE] 'git' already installed.";
+ fi
+
+ # TREE
+ TREE_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' tree|grep "install ok installed")
+ if [[ "" == "$TREE_INSTALLED" ]]; then
+ sudo apt-get --force-yes --yes install tree
+ else
+ echo " [PREREQUISITE] 'tree' already installed.";
+ fi
+
+ # gcc-arm-linux-gnueabihf
+ GCC_ARMHF_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' gcc-arm-linux-gnueabihf)
+ 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
+ GCC_AARCH64_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' gcc-aarch64-linux-gnu)
+ 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
+
+ # libgpiod2
+ LIBGPIOD_DEV_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' libgpiod-dev)
+ if [[ "$?" == "1" ]] ; then
+ echo " [PREREQUISITE] installing 'libgpiod-dev'...";
+ sudo apt-get --force-yes --yes install libgpiod-dev
+ else
+ echo " [PREREQUISITE] 'libgpiod-dev' already installed.";
+ fi
+
+ # libgpiod-dev
+ LIBGPIOD_2_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' libgpiod-dev)
+ if [[ "$?" == "1" ]] ; then
+ echo " [PREREQUISITE] installing 'libgpiod-dev'...";
+ sudo apt-get --force-yes --yes install libgpiod-dev
+ else
+ echo " [PREREQUISITE] 'libgpiod-dev' already installed.";
+ fi
+
+ # gpiod
+ GPIOD_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' gpiod)
+ if [[ "$?" == "1" ]] ; then
+ echo " [PREREQUISITE] installing 'gpiod'...";
+ sudo apt-get --force-yes --yes install gpiod
+ else
+ echo " [PREREQUISITE] 'gpiod' already installed.";
+ fi
+
+ # autoconf
+ LIBGPIOD_DEV_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' autoconf)
+ if [[ "$?" == "1" ]] ; then
+ echo " [PREREQUISITE] installing 'autoconf'...";
+ sudo apt-get --force-yes --yes install autoconf
+ else
+ echo " [PREREQUISITE] 'autoconf' already installed.";
+ fi
+
+ # pkg-config
+ PKG_CONFIG_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' pkg-config)
+ 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
+ LIBTOOL_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' libtool)
+ if [[ "$?" == "1" ]] ; then
+ echo " [PREREQUISITE] installing 'libtool'...";
+ sudo apt-get --force-yes --yes install libtool
+ else
+ echo " [PREREQUISITE] 'libtool' already installed.";
+ fi
+
+ # autoconf
+ AUTOCONF_ARCHIVE_INSTALLED=$(dpkg-query -W --showformat='${Status}\n' autoconf-archive)
+ 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
+fi
diff --git a/libraries/pi4j-library-gpiod/src/main/native/build.sh b/libraries/pi4j-library-gpiod/src/main/native/build.sh
new file mode 100755
index 00000000..64ee5b0a
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/native/build.sh
@@ -0,0 +1,132 @@
+#!/bin/bash -e
+###
+# #%L
+# **********************************************************************
+# ORGANIZATION : Pi4J
+# PROJECT : Pi4J :: JNI Native Binding Library for GpioD
+# 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 GPIOD LIBRARY NATIVE BUILD *"
+echo "* *"
+echo "**********************************************************************"
+echo
+
+# ------------------------------------------------------
+# VALIDATE BUILD PLATFORM; PRECONDITIONS
+# ------------------------------------------------------
+
+# validate compatible OS/Kernel
+KERNEL=$(uname -s)
+if [[ ("$KERNEL" != "Linux") ]]; then
+ echo "This native build is only supported on Linux-based systems running on an Intel/AMD or ARM 64-bit platform."
+ echo "BUILD ABORTED; REASON: KERNEL='$KERNEL'; EXPECTED='Linux'"
+ echo "(NOTE: You can run this build using the Pi4J Docker Builder images from OSX, Windows, Linux.)"
+ exit 1
+fi
+
+# validate compatible CPU architecture
+ARCHITECTURE=$(uname -m)
+if [[ (("$ARCHITECTURE" != "aarch64") && ("$ARCHITECTURE" != "amd64") && ("$ARCHITECTURE" != "x86_64")) ]]; then
+ echo "This native build is only supported on Linux-based systems running on an Intel/AMD or ARM 64-bit platform."
+ echo "BUILD ABORTED; REASON: ARCHITECTURE='$ARCHITECTURE'; EXPECTED='aarch64|amd64|x86_64'"
+ exit 1
+fi
+
+# ------------------------------------------------------
+# ENSURE DEPENDENCY SCRIPTS ARE EXECUTABLE
+# ------------------------------------------------------
+# set executable permissions on build scripts
+chmod +x build-prerequisites.sh
+chmod +x build-libpi4j.sh
+
+# ------------------------------------------------------
+# INSTALL BUILD PREREQUISITES
+# ------------------------------------------------------
+echo
+echo "====================================="
+echo " INSTALLING Pi4J BUILD PREREQUISITES "
+echo "====================================="
+echo
+
+# if running inside a Pi4J Docker Builder image, then there is no need to install prerequisites
+if [[ "${PI4J_BUILDER}" != "" ]]; then
+ echo "Running inside a Pi4J Docker Builder image; [version=${PI4J_BUILDER}; arch=${PI4J_BUILDER_ARCH}]"
+ echo "No need to check or install build environment prerequisites."
+else
+ # if this is a Linux-based system and a 64-bit Intel/AMD or ARM platform, then we can install the prerequisites
+ # download and install development prerequisites
+ ./build-prerequisites.sh
+fi
+
+# ------------------------------------------------------
+# JAVA_HOME ENVIRONMENT VARIABLE
+# ------------------------------------------------------
+echo
+echo "========================================="
+echo " CHECKING JAVA_HOME ENVIRONMENT VARIABLE "
+echo "========================================="
+echo
+if [[ -n "$JAVA_HOME" ]]; then
+ echo "'JAVA_HOME' already defined as: $JAVA_HOME";
+else
+ export JAVA_HOME=$(readlink -f /usr/bin/javac | sed "s:bin/javac::")
+ echo "'JAVA_HOME' was not defined; attempting to use: $JAVA_HOME";
+fi
+
+# ------------------------------------------------------
+# BUILD NATIVE LIBRARIES FOR ARMv6,ARMv7,ARMv8 32-BIT (ARMHF)
+# USING THE LOCALLY INSTALLED ARM CROSS-COMPILER
+# ------------------------------------------------------
+export CROSS_PREFIX=arm-linux-gnueabihf-
+export CC=arm-linux-gnueabihf-gcc
+export ARCH=armhf
+export HOST=arm-linux-gnueabihf
+./build-libpi4j.sh $@
+
+# ------------------------------------------------------
+# BUILD NATIVE LIBRARIES FOR ARMv8 64-BIT (ARM64)
+# USING THE LOCALLY INSTALLED ARM64 CROSS-COMPILER
+# ------------------------------------------------------
+export CROSS_PREFIX=aarch64-linux-gnu-
+export CC=aarch64-linux-gnu-gcc
+export ARCH=aarch64
+export HOST=aarch64-linux-gnu
+./build-libpi4j.sh $@
+
+echo "======================================"
+echo " Pi4J GPIOD LIBRARY NATIVE ARTIFACTS "
+echo "======================================"
+tree -R lib
+
+echo
+echo "**********************************************************************"
+echo "* *"
+echo "* Pi4J GPIOD LIBRARY NATIVE BUILD *"
+echo "* *"
+echo "**********************************************************************"
+echo
\ No newline at end of file
diff --git a/libraries/pi4j-library-gpiod/src/main/native/com_pi4j_library_gpiod_internal_GpioD.c b/libraries/pi4j-library-gpiod/src/main/native/com_pi4j_library_gpiod_internal_GpioD.c
new file mode 100644
index 00000000..a57522cd
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/native/com_pi4j_library_gpiod_internal_GpioD.c
@@ -0,0 +1,962 @@
+
+#include
+#include
+#include "com_pi4j_library_gpiod_internal_GpioD.h"
+
+// Compile using:
+// gcc -I /usr/lib/jvm/java-11-openjdk-amd64/include/ -I /usr/lib/jvm/java-11-openjdk-amd64/include/linux/ -lgpiod -I . -c com_pi4j_library_gpiod_internal_GpioD.c
+
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1open
+ (JNIEnv* env, jclass javaClass, jstring path) {
+ struct gpiod_chip* chip;
+ const char* nativeString = (*env)->GetStringUTFChars(env, path, NULL);
+ chip = gpiod_chip_open(nativeString);
+ (*env)->ReleaseStringUTFChars(env, path, nativeString);
+
+ if(chip == NULL) {
+ return NULL;
+ }
+ jclass cls = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "", "(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) chip);
+}
+
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1close
+ (JNIEnv* env, jclass javaClass, jlong chipPtr) {
+ gpiod_chip_close((struct gpiod_chip*) (uintptr_t) chipPtr);
+ }
+
+JNIEXPORT jstring JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1name
+ (JNIEnv* env, jclass javaClass, jlong chipPtr) {
+ const char* name = gpiod_chip_name((struct gpiod_chip*) (uintptr_t) chipPtr);
+ jstring jStrName = (*env)->NewStringUTF(env, name);
+ return jStrName;
+ }
+
+JNIEXPORT jstring JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1label
+ (JNIEnv* env, jclass javaClass, jlong chipPtr) {
+ const char* label = gpiod_chip_label((struct gpiod_chip*) (uintptr_t) chipPtr);
+ jstring jStrName = (*env)->NewStringUTF(env, label);
+ return jStrName;
+}
+
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1num_1lines
+ (JNIEnv* env, jclass javaClass, jlong chipPtr) {
+ unsigned int num_lines = gpiod_chip_num_lines((struct gpiod_chip*) (uintptr_t) chipPtr);
+ return num_lines;
+}
+
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1get_1line
+ (JNIEnv* env, jclass javaClass, jlong chipPtr, jint offset) {
+ struct gpiod_line* line;
+ line = gpiod_chip_get_line((struct gpiod_chip*) (uintptr_t) chipPtr, offset);
+ if(line == NULL) {
+ return NULL;
+ }
+ jclass cls = (*env)->FindClass(env,"java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "","(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) line);
+}
+
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1get_1lines
+ (JNIEnv* env, jclass javaClass, jlong chipPtr, jintArray offsets, jint num_offsets, jlong lineBulkPtr) {
+ jint* c_offsets = (*env)->GetIntArrayElements(env, offsets, 0);
+ int returnVal = gpiod_chip_get_lines((struct gpiod_chip*) (uintptr_t) chipPtr, (unsigned int*) c_offsets, num_offsets, (struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr);
+ (*env)->ReleaseIntArrayElements(env, offsets, c_offsets, 0);
+ return returnVal;
+}
+
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1get_1all_1lines
+ (JNIEnv* env, jclass javaClass, jlong chipPtr, jlong lineBulkPtr) {
+ return gpiod_chip_get_all_lines((struct gpiod_chip*) (uintptr_t) chipPtr, (struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr);
+}
+
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1find_1line
+ (JNIEnv* env, jclass javaClass, jlong chipPtr, jstring name) {
+ const char* c_name = (*env)->GetStringUTFChars(env, name, NULL);
+ struct gpiod_line* line = gpiod_chip_find_line((struct gpiod_chip*) (uintptr_t) chipPtr, c_name);
+ (*env)->ReleaseStringUTFChars(env, name, c_name);
+
+ if(line == NULL) {
+ return NULL;
+ }
+ jclass cls = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "","(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) line);
+}
+
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bulk_1free
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr) {
+ free((struct gpiod_line_bulk*) (uintptr_t) bulkPtr);
+}
+
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1bulk_1init
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr) {
+ gpiod_line_bulk_init((struct gpiod_line_bulk*) (uintptr_t) bulkPtr);
+}
+
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bulk_1new
+ (JNIEnv* env, jclass javaClass) {
+ struct gpiod_line_bulk* bulkPtr = (struct gpiod_line_bulk*) malloc(sizeof(struct gpiod_line_bulk));
+ jclass cls = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "","(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) bulkPtr);
+}
+
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bulk_1add
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr, jlong linePtr) {
+ gpiod_line_bulk_add((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr, (struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+JNIEXPORT jlong JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bulk_1get_1line
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr, jint offset) {
+ return (jlong) (uintptr_t) gpiod_line_bulk_get_line((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr, offset);
+}
+
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bulk_1num_1lines
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr) {
+ return gpiod_line_bulk_num_lines((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_offset
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1offset
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_offset((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_name
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1name
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ const char* c_name = gpiod_line_name((struct gpiod_line*) (uintptr_t) linePtr);
+ return (*env)->NewStringUTF(env, c_name);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_consumer
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1consumer
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ const char* c_name = gpiod_line_consumer((struct gpiod_line*) (uintptr_t) linePtr);
+ return (*env)->NewStringUTF(env, c_name);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_direction
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1direction
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_direction((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_active_state
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1active_1state
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_active_state((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_bias
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bias
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_bias((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_is_used
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1is_1used
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_is_used((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_is_open_drain
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1is_1open_1drain
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_is_open_drain((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_is_open_source
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1is_1open_1source
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_is_open_source((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_update
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1update
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_update((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request
+ * Signature: (JJI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jlong requestConfigPtr, jint defaultVal) {
+ return gpiod_line_request((struct gpiod_line*) (uintptr_t) linePtr, (struct gpiod_line_request_config*) (uintptr_t) linePtr, defaultVal);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_input
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1input
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jstring consumer) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_input((struct gpiod_line*) (uintptr_t) linePtr, c_consumer);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_output
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1output
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jstring consumer, jint defaultVal) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_output((struct gpiod_line*) (uintptr_t) linePtr, c_consumer, defaultVal);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_rising_edge_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1rising_1edge_1events
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jstring consumer) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_rising_edge_events((struct gpiod_line*) (uintptr_t) linePtr, c_consumer);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_falling_edge_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1falling_1edge_1events
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jstring consumer) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_falling_edge_events((struct gpiod_line*) (uintptr_t) linePtr, c_consumer);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_both_edges_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1both_1edges_1events
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jstring consumer) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_both_edges_events((struct gpiod_line*) (uintptr_t) linePtr, c_consumer);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_input_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1input_1flags
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jstring consumer, jint flags) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_input_flags((struct gpiod_line*) (uintptr_t) linePtr, c_consumer, flags);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_output_flags
+ * Signature: (JLjava/lang/String;II)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1output_1flags
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jstring consumer, jint flags, jint defaultVal) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_output_flags((struct gpiod_line*) (uintptr_t) linePtr, c_consumer, flags, defaultVal);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_rising_edge_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1rising_1edge_1events_1flags
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jstring consumer, jint flags) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_rising_edge_events_flags((struct gpiod_line*) (uintptr_t) linePtr, c_consumer, flags);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_falling_edge_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1falling_1edge_1events_1flags
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jstring consumer, jint flags) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_falling_edge_events_flags((struct gpiod_line*) (uintptr_t) linePtr, c_consumer, flags);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_both_edges_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1both_1edges_1events_1flags
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jstring consumer, jint flags) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_both_edges_events_flags((struct gpiod_line*) (uintptr_t) linePtr, c_consumer, flags);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk
+ * Signature: (JJ[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr, jlong requestConfigPtr, jintArray defaultVals) {
+ jint* c_defaultVals = (*env)->GetIntArrayElements(env, defaultVals, 0);
+ int result = gpiod_line_request_bulk((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr, (struct gpiod_line_request_config*) (uintptr_t) requestConfigPtr, c_defaultVals);
+ (*env)->ReleaseIntArrayElements(env, defaultVals, c_defaultVals, 0);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_input
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1input
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr, jstring consumer) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_bulk_input((struct gpiod_line_bulk*) (uintptr_t) bulkPtr, c_consumer);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_output
+ * Signature: (JLjava/lang/String;[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1output
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr, jstring consumer, jintArray defaultVals) {
+ jint* c_defaultVals = (*env)->GetIntArrayElements(env, defaultVals, 0);
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_bulk_output((struct gpiod_line_bulk*) (uintptr_t) bulkPtr, c_consumer, c_defaultVals);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ (*env)->ReleaseIntArrayElements(env, defaultVals, c_defaultVals, 0);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_rising_edge_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1rising_1edge_1events
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr, jstring consumer) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_bulk_rising_edge_events((struct gpiod_line_bulk*) (uintptr_t) bulkPtr, c_consumer);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_falling_edge_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1falling_1edge_1events
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr, jstring consumer) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_bulk_falling_edge_events((struct gpiod_line_bulk*) (uintptr_t) bulkPtr, c_consumer);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_both_edges_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1both_1edges_1events
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr, jstring consumer) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_bulk_both_edges_events((struct gpiod_line_bulk*) (uintptr_t) bulkPtr, c_consumer);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_input_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1input_1flags
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr, jstring consumer, jint flags) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_bulk_input_flags((struct gpiod_line_bulk*) (uintptr_t) bulkPtr, c_consumer, flags);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_output_flags
+ * Signature: (JLjava/lang/String;I[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1output_1flags
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr, jstring consumer, jint flags, jintArray defaultVals) {
+ jint* c_defaultVals = (*env)->GetIntArrayElements(env, defaultVals, 0);
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_bulk_output_flags((struct gpiod_line_bulk*) (uintptr_t) bulkPtr, c_consumer, flags, c_defaultVals);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ (*env)->ReleaseIntArrayElements(env, defaultVals, c_defaultVals, 0);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_rising_edge_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1rising_1edge_1events_1flags
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr, jstring consumer, jint flags) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_bulk_rising_edge_events_flags((struct gpiod_line_bulk*) (uintptr_t) bulkPtr, c_consumer, flags);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_falling_edge_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1falling_1edge_1events_1flags
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr, jstring consumer, jint flags) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_bulk_falling_edge_events_flags((struct gpiod_line_bulk*) (uintptr_t) bulkPtr, c_consumer, flags);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_both_edges_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1both_1edges_1events_1flags
+ (JNIEnv* env, jclass javaClass, jlong bulkPtr, jstring consumer, jint flags) {
+ const char* c_consumer = (*env)->GetStringUTFChars(env, consumer, NULL);
+ int result = gpiod_line_request_bulk_both_edges_events_flags((struct gpiod_line_bulk*) (uintptr_t) bulkPtr, c_consumer, flags);
+ (*env)->ReleaseStringUTFChars(env, consumer, c_consumer);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_release
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1release
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ gpiod_line_release((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_release_bulk
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1release_1bulk
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr) {
+ gpiod_line_release_bulk((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_is_requested
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1is_1requested
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_is_requested((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_is_free
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1is_1free
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_is_free((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_get_value
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1get_1value
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_get_value((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_get_value_bulk
+ * Signature: (J[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1get_1value_1bulk
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr, jintArray values) {
+ jint* c_values = (*env)->GetIntArrayElements(env, values, 0);
+ int result = gpiod_line_get_value_bulk((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr, c_values);
+ (*env)->ReleaseIntArrayElements(env, values, c_values, 0);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_value
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1value
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jint value) {
+ return gpiod_line_set_value((struct gpiod_line*) (uintptr_t) linePtr, value);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_value_bulk
+ * Signature: (J[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1value_1bulk
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr, jintArray values) {
+ jint* c_values = (*env)->GetIntArrayElements(env, values, 0);
+ int result = gpiod_line_set_value_bulk((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr, c_values);
+ (*env)->ReleaseIntArrayElements(env, values, c_values, 0);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_config
+ * Signature: (JIII)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1config
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jint direction, jint flags, jint value) {
+ return gpiod_line_set_config((struct gpiod_line*) (uintptr_t) linePtr, direction, flags, value);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_config_bulk
+ * Signature: (JII[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1config_1bulk
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr, jint direction, jint flags, jintArray values) {
+ jint* c_values = (*env)->GetIntArrayElements(env, values, 0);
+ int result = gpiod_line_set_config_bulk((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr, direction, flags, c_values);
+ (*env)->ReleaseIntArrayElements(env, values, c_values, 0);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_flags
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1flags
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jint flags) {
+ return gpiod_line_set_flags((struct gpiod_line*) (uintptr_t) linePtr, flags);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_flags_bulk
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1flags_1bulk
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr, jint flags) {
+ return gpiod_line_set_flags_bulk((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr, flags);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_direction_input
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1direction_1input
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return gpiod_line_set_direction_input((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_direction_input_bulk
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1direction_1input_1bulk
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr) {
+ return gpiod_line_set_direction_input_bulk((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_direction_output
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1direction_1output
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jint value) {
+ return gpiod_line_set_direction_output((struct gpiod_line*) (uintptr_t) linePtr, value);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_direction_output_bulk
+ * Signature: (J[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1direction_1output_1bulk
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr, jintArray values) {
+ jint* c_values = (*env)->GetIntArrayElements(env, values, 0);
+ int result = gpiod_line_set_direction_output_bulk((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr, c_values);
+ (*env)->ReleaseIntArrayElements(env, values, c_values, 0);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_wait
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1wait
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jlong timeoutNs) {
+ struct timespec timeout;
+ timeout.tv_sec = timeoutNs / 1000000000;
+ timeout.tv_nsec = timeoutNs % 1000000000;
+ return gpiod_line_event_wait((struct gpiod_line*) (uintptr_t) linePtr, &timeout);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_wait_bulk
+ * Signature: (JJJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1wait_1bulk
+ (JNIEnv* env, jclass javaClass, jlong lineBulkPtr, jlong timeoutNs, jlong eventBulkPtr) {
+ struct timespec timeout;
+ timeout.tv_sec = timeoutNs / 1000000000;
+ timeout.tv_nsec = timeoutNs % 1000000000;
+ int result = gpiod_line_event_wait_bulk((struct gpiod_line_bulk*) (uintptr_t) lineBulkPtr, &timeout, (struct gpiod_line_bulk*) (uintptr_t) eventBulkPtr);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_read
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1read
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jlong eventPtr) {
+ return gpiod_line_event_read((struct gpiod_line*) (uintptr_t) linePtr, (struct gpiod_line_event*) (uintptr_t) eventPtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_read_multiple
+ * Signature: (J[JI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1read_1multiple
+ (JNIEnv* env, jclass javaClass, jlong linePtr, jlongArray events, jint numEvents) {
+ jlong* c_events = (*env)->GetLongArrayElements(env, events, 0);
+ int result = gpiod_line_event_read_multiple((struct gpiod_line*) (uintptr_t) linePtr, (struct gpiod_line_event*) (uintptr_t) c_events, numEvents);
+ (*env)->ReleaseLongArrayElements(env, events, c_events, 0);
+ return result;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_get
+ * Signature: (Ljava/lang/String;I)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1get
+ (JNIEnv* env, jclass javaClass, jstring device, jint offset) {
+ const char* c_device = (*env)->GetStringUTFChars(env, device, NULL);
+ struct gpiod_line* found = gpiod_line_get(c_device, offset);
+ (*env)->ReleaseStringUTFChars(env, device, c_device);
+
+ if(found == NULL) {
+ return NULL;
+ }
+ jclass cls = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "", "(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) found);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_find
+ * Signature: (Ljava/lang/String;)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1find
+ (JNIEnv* env, jclass javaClass, jstring name) {
+ const char* c_name = (*env)->GetStringUTFChars(env, name, NULL);
+ struct gpiod_line* found = gpiod_line_find(c_name);
+ (*env)->ReleaseStringUTFChars(env, name, c_name);
+
+ if(found == NULL) {
+ return NULL;
+ }
+ jclass cls = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "", "(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) found);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_close_chip
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1close_1chip
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ gpiod_line_close_chip((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_get_chip
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1get_1chip
+ (JNIEnv* env, jclass javaClass, jlong linePtr) {
+ return (jlong) (uintptr_t) gpiod_line_get_chip((struct gpiod_line*) (uintptr_t) linePtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_chip_iter_new
+ * Signature: ()Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1chip_1iter_1new
+ (JNIEnv* env, jclass javaClass) {
+ struct gpiod_chip_iter* iter = gpiod_chip_iter_new();
+
+ if(iter == NULL) {
+ return NULL;
+ }
+ jclass cls = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "", "(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) iter);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_iter_free
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1iter_1free
+ (JNIEnv* env, jclass javaClass, jlong chipIterPtr) {
+ gpiod_chip_iter_free((struct gpiod_chip_iter*) (uintptr_t) chipIterPtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_iter_free_noclose
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1iter_1free_1noclose
+ (JNIEnv* env, jclass javaClass, jlong chipIterPtr) {
+ gpiod_chip_iter_free_noclose((struct gpiod_chip_iter*) (uintptr_t) chipIterPtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_iter_next
+ * Signature: (J)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1iter_1next
+ (JNIEnv* env, jclass javaClass, jlong chipIterPtr) {
+ struct gpiod_chip* chip = gpiod_chip_iter_next((struct gpiod_chip_iter*) (uintptr_t) chipIterPtr);
+
+ if(chip == NULL) {
+ return NULL;
+ }
+ jclass cls = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "", "(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) chip);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_iter_next_noclose
+ * Signature: (J)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1iter_1next_1noclose
+ (JNIEnv* env, jclass javaClass, jlong chipIterPtr) {
+ struct gpiod_chip* chip = gpiod_chip_iter_next_noclose((struct gpiod_chip_iter*) (uintptr_t) chipIterPtr);
+
+ if(chip == NULL) {
+ return NULL;
+ }
+ jclass cls = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "", "(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) chip);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_iter_new
+ * Signature: (J)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1iter_1new
+ (JNIEnv* env, jclass javaClass, jlong lineIterPtr) {
+ struct gpiod_line_iter* iter = gpiod_line_iter_new((struct gpiod_chip*) (uintptr_t) lineIterPtr);
+
+ if(iter == NULL) {
+ return NULL;
+ }
+ jclass cls = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "", "(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) iter);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_iter_free
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1iter_1free
+ (JNIEnv* env, jclass javaClass, jlong lineIterPtr) {
+ gpiod_line_iter_free((struct gpiod_line_iter*) (uintptr_t) lineIterPtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_iter_next
+ * Signature: (J)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1iter_1next
+ (JNIEnv* env, jclass javaClass, jlong lineIterPtr) {
+ struct gpiod_line* line = gpiod_line_iter_next((struct gpiod_line_iter*) (uintptr_t) lineIterPtr);
+
+ if(line == NULL) {
+ return NULL;
+ }
+ jclass cls = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "", "(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) line);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_get_timespec
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1get_1timespec
+ (JNIEnv* env, jclass javaClass, jlong eventPtr) {
+ struct timespec ts = ((struct gpiod_line_event*) (uintptr_t) eventPtr)->ts;
+ jlong tsNs = ts.tv_nsec;
+ tsNs += ts.tv_sec * 1000000000;
+ return tsNs;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_get_type
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1get_1type
+ (JNIEnv* env, jclass javaClass, jlong eventPtr) {
+ return ((struct gpiod_line_event*) (uintptr_t) eventPtr)->event_type;
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_new
+ * Signature: ()Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1new
+ (JNIEnv* env, jclass javaClass) {
+ struct gpiod_line_event* eventPtr = (struct gpiod_line_event*) malloc(sizeof(struct gpiod_line_event));
+ if(eventPtr == NULL) {
+ return NULL;
+ }
+ jclass cls = (*env)->FindClass(env, "java/lang/Long");
+ jmethodID longConstructor = (*env)->GetMethodID(env, cls, "","(J)V");
+ return (*env)->NewObject(env, cls, longConstructor, (jlong) (uintptr_t) eventPtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_free
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1free
+ (JNIEnv* env, jclass javaClass, jlong eventPtr) {
+ free((struct gpiod_line_event*) (uintptr_t) eventPtr);
+}
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_version_string
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1version_1string
+ (JNIEnv* env, jclass javaClass) {
+ return (*env)->NewStringUTF(env, gpiod_version_string());
+}
\ No newline at end of file
diff --git a/libraries/pi4j-library-gpiod/src/main/native/com_pi4j_library_gpiod_internal_GpioD.h b/libraries/pi4j-library-gpiod/src/main/native/com_pi4j_library_gpiod_internal_GpioD.h
new file mode 100644
index 00000000..a8deb9fe
--- /dev/null
+++ b/libraries/pi4j-library-gpiod/src/main/native/com_pi4j_library_gpiod_internal_GpioD.h
@@ -0,0 +1,685 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class com_pi4j_library_gpiod_internal_GpioD */
+
+#ifndef _Included_com_pi4j_library_gpiod_internal_GpioD
+#define _Included_com_pi4j_library_gpiod_internal_GpioD
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_open
+ * Signature: (Ljava/lang/String;)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1open
+ (JNIEnv *, jclass, jstring);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_close
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1close
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_name
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1name
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_label
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1label
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_num_lines
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1num_1lines
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_get_line
+ * Signature: (JI)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1get_1line
+ (JNIEnv *, jclass, jlong, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_get_lines
+ * Signature: (J[IIJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1get_1lines
+ (JNIEnv *, jclass, jlong, jintArray, jint, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_get_all_lines
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1get_1all_1lines
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_find_line
+ * Signature: (JLjava/lang/String;)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1find_1line
+ (JNIEnv *, jclass, jlong, jstring);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_bulk_free
+ * Signature: (J)Ljava/lang/Long;
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bulk_1free
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_bulk_init
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1bulk_1init
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_bulk_new
+ * Signature: ()Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bulk_1new
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_bulk_add
+ * Signature: (JJ)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bulk_1add
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_bulk_get_line
+ * Signature: (JI)J
+ */
+JNIEXPORT jlong JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bulk_1get_1line
+ (JNIEnv *, jclass, jlong, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_bulk_num_lines
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bulk_1num_1lines
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_offset
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1offset
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_name
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1name
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_consumer
+ * Signature: (J)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1consumer
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_direction
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1direction
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_active_state
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1active_1state
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_bias
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1bias
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_is_used
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1is_1used
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_is_open_drain
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1is_1open_1drain
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_is_open_source
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1is_1open_1source
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_update
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1update
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request
+ * Signature: (JJI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request
+ (JNIEnv *, jclass, jlong, jlong, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_input
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1input
+ (JNIEnv *, jclass, jlong, jstring);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_output
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1output
+ (JNIEnv *, jclass, jlong, jstring, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_rising_edge_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1rising_1edge_1events
+ (JNIEnv *, jclass, jlong, jstring);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_falling_edge_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1falling_1edge_1events
+ (JNIEnv *, jclass, jlong, jstring);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_both_edges_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1both_1edges_1events
+ (JNIEnv *, jclass, jlong, jstring);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_input_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1input_1flags
+ (JNIEnv *, jclass, jlong, jstring, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_output_flags
+ * Signature: (JLjava/lang/String;II)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1output_1flags
+ (JNIEnv *, jclass, jlong, jstring, jint, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_rising_edge_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1rising_1edge_1events_1flags
+ (JNIEnv *, jclass, jlong, jstring, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_falling_edge_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1falling_1edge_1events_1flags
+ (JNIEnv *, jclass, jlong, jstring, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_both_edges_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1both_1edges_1events_1flags
+ (JNIEnv *, jclass, jlong, jstring, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk
+ * Signature: (JJ[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk
+ (JNIEnv *, jclass, jlong, jlong, jintArray);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_input
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1input
+ (JNIEnv *, jclass, jlong, jstring);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_output
+ * Signature: (JLjava/lang/String;[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1output
+ (JNIEnv *, jclass, jlong, jstring, jintArray);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_rising_edge_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1rising_1edge_1events
+ (JNIEnv *, jclass, jlong, jstring);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_falling_edge_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1falling_1edge_1events
+ (JNIEnv *, jclass, jlong, jstring);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_both_edges_events
+ * Signature: (JLjava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1both_1edges_1events
+ (JNIEnv *, jclass, jlong, jstring);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_input_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1input_1flags
+ (JNIEnv *, jclass, jlong, jstring, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_output_flags
+ * Signature: (JLjava/lang/String;I[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1output_1flags
+ (JNIEnv *, jclass, jlong, jstring, jint, jintArray);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_rising_edge_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1rising_1edge_1events_1flags
+ (JNIEnv *, jclass, jlong, jstring, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_falling_edge_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1falling_1edge_1events_1flags
+ (JNIEnv *, jclass, jlong, jstring, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_request_bulk_both_edges_events_flags
+ * Signature: (JLjava/lang/String;I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1request_1bulk_1both_1edges_1events_1flags
+ (JNIEnv *, jclass, jlong, jstring, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_release
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1release
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_release_bulk
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1release_1bulk
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_is_requested
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1is_1requested
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_is_free
+ * Signature: (J)Z
+ */
+JNIEXPORT jboolean JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1is_1free
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_get_value
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1get_1value
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_get_value_bulk
+ * Signature: (J[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1get_1value_1bulk
+ (JNIEnv *, jclass, jlong, jintArray);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_value
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1value
+ (JNIEnv *, jclass, jlong, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_value_bulk
+ * Signature: (J[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1value_1bulk
+ (JNIEnv *, jclass, jlong, jintArray);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_config
+ * Signature: (JIII)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1config
+ (JNIEnv *, jclass, jlong, jint, jint, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_config_bulk
+ * Signature: (JII[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1config_1bulk
+ (JNIEnv *, jclass, jlong, jint, jint, jintArray);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_flags
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1flags
+ (JNIEnv *, jclass, jlong, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_flags_bulk
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1flags_1bulk
+ (JNIEnv *, jclass, jlong, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_direction_input
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1direction_1input
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_direction_input_bulk
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1direction_1input_1bulk
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_direction_output
+ * Signature: (JI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1direction_1output
+ (JNIEnv *, jclass, jlong, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_set_direction_output_bulk
+ * Signature: (J[I)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1set_1direction_1output_1bulk
+ (JNIEnv *, jclass, jlong, jintArray);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_wait
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1wait
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_wait_bulk
+ * Signature: (JJJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1wait_1bulk
+ (JNIEnv *, jclass, jlong, jlong, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_read
+ * Signature: (JJ)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1read
+ (JNIEnv *, jclass, jlong, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_read_multiple
+ * Signature: (J[JI)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1read_1multiple
+ (JNIEnv *, jclass, jlong, jlongArray, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_get
+ * Signature: (Ljava/lang/String;I)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1get
+ (JNIEnv *, jclass, jstring, jint);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_find
+ * Signature: (Ljava/lang/String;)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1find
+ (JNIEnv *, jclass, jstring);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_close_chip
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1close_1chip
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_get_chip
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1get_1chip
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_chip_iter_new
+ * Signature: ()Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1chip_1iter_1new
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_iter_free
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1iter_1free
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_iter_free_noclose
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1iter_1free_1noclose
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_iter_next
+ * Signature: (J)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1iter_1next
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_chip_iter_next_noclose
+ * Signature: (J)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1chip_1iter_1next_1noclose
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_iter_new
+ * Signature: (J)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1iter_1new
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_iter_free
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1iter_1free
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: gpiod_line_iter_next
+ * Signature: (J)Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_gpiod_1line_1iter_1next
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_get_timespec
+ * Signature: (J)J
+ */
+JNIEXPORT jlong JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1get_1timespec
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_get_type
+ * Signature: (J)I
+ */
+JNIEXPORT jint JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1get_1type
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_new
+ * Signature: ()Ljava/lang/Long;
+ */
+JNIEXPORT jobject JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1new
+ (JNIEnv *, jclass);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_line_event_free
+ * Signature: (J)V
+ */
+JNIEXPORT void JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1line_1event_1free
+ (JNIEnv *, jclass, jlong);
+
+/*
+ * Class: com_pi4j_library_gpiod_internal_GpioD
+ * Method: c_gpiod_version_string
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_com_pi4j_library_gpiod_internal_GpioD_c_1gpiod_1version_1string
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/libraries/pi4j-library/pom.xml b/libraries/pi4j-library/pom.xml
index bcea620f..ce8a507a 100644
--- a/libraries/pi4j-library/pom.xml
+++ b/libraries/pi4j-library/pom.xml
@@ -29,6 +29,7 @@
../pi4j-library-pigpio
../pi4j-library-linuxfs
+ ../pi4j-library-gpiod
diff --git a/pi4j-distribution/pom.xml b/pi4j-distribution/pom.xml
index f4f7b216..e1bfaad8 100644
--- a/pi4j-distribution/pom.xml
+++ b/pi4j-distribution/pom.xml
@@ -52,6 +52,11 @@
pi4j-plugin-linuxfs
${project.version}
+
+ com.pi4j
+ pi4j-plugin-gpiod
+ ${project.version}
+
@@ -64,6 +69,11 @@
pi4j-library-linuxfs
${project.version}
+
+ com.pi4j
+ pi4j-library-gpiod
+ ${project.version}
+
+
+ com.pi4j
+ pi4j-library-gpiod
+ ${project.version}
+ armhf
+ so
+
+
+ com.pi4j
+ pi4j-library-gpiod
+ ${project.version}
+ aarch64
+ so
+
+
diff --git a/pi4j-test/pom.xml b/pi4j-test/pom.xml
index a61b14bf..8a5899bd 100644
--- a/pi4j-test/pom.xml
+++ b/pi4j-test/pom.xml
@@ -31,6 +31,85 @@
pi4j-plugin-mock
${project.version}
+
+
+
+ com.pi4j
+ pi4j-library-pigpio
+ ${project.version}
+
+
+ com.pi4j
+ pi4j-library-linuxfs
+ ${project.version}
+
+
+ com.pi4j
+ pi4j-library-gpiod
+ ${project.version}
+
+
+
+
+
+ com.pi4j
+ pi4j-library-pigpio
+ ${project.version}
+ armhf
+ so
+
+
+ com.pi4j
+ pi4j-library-pigpio
+ ${project.version}
+ aarch64
+ so
+
+
+
+
+ com.pi4j
+ pi4j-library-linuxfs
+ ${project.version}
+ armhf
+ so
+
+
+ com.pi4j
+ pi4j-library-linuxfs
+ ${project.version}
+ aarch64
+ so
+
+
+
+
+ com.pi4j
+ pi4j-library-gpiod
+ ${project.version}
+ armhf
+ so
+
+
+ com.pi4j
+ pi4j-library-gpiod
+ ${project.version}
+ aarch64
+ so
+
+
+ com.pi4j
+ pi4j-plugin-gpiod
+ ${project.version}
+
+
+ com.pi4j
+ pi4j-plugin-linuxfs
+ ${project.version}
+
+
@@ -107,47 +186,98 @@
+
+
-
-
- org.apache.maven.plugins
- maven-antrun-plugin
-
+
+
+
+ remote-run
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ process-sources
+
+ copy-dependencies
+
+
+ ${project.build.directory}/distribution
+ runtime
+ false
+ false
+ true
+ true
+
+
+
+
-
-
- transfer-compiled-pi4j-jar
- install
-
- run
-
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ ${project.build.directory}/distribution
-
-
-
+
-
-
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+ transfer
+ install
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.apache.ant
+ ant-jsch
+ ${ant-jsch.version}
+
+
+
+
+
+
+
diff --git a/pi4j-test/src/main/java/com/pi4j/test/GpiodTest.java b/pi4j-test/src/main/java/com/pi4j/test/GpiodTest.java
new file mode 100644
index 00000000..f0ec4eaa
--- /dev/null
+++ b/pi4j-test/src/main/java/com/pi4j/test/GpiodTest.java
@@ -0,0 +1,31 @@
+package com.pi4j.test;
+
+import com.pi4j.Pi4J;
+import com.pi4j.context.Context;
+import com.pi4j.plugin.gpiod.provider.gpio.digital.GpioDDigitalInputProvider;
+import com.pi4j.plugin.gpiod.provider.gpio.digital.GpioDDigitalOutputProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GpiodTest {
+
+ private static final Logger logger = LoggerFactory.getLogger(Main.class);
+
+ public static void main(String[] args) throws InterruptedException {
+ System.out.println("Attach remote now!");
+ Thread.sleep(1000 * 10);
+ Context pi4j = Pi4J.newContextBuilder()
+ .add(GpioDDigitalOutputProvider.newInstance(), GpioDDigitalInputProvider.newInstance())
+ .build();
+ //Context pi4j = Pi4J.newAutoContext();
+
+ logger.info("\r\n\r\n-----------------------------------\r\n"
+ + "Pi4J GPIOD - Runtime Information\r\n"
+ + "-----------------------------------");
+ pi4j.describe().print(System.out);
+
+
+ // shutdown Pi4J
+ pi4j.shutdown();
+ }
+}
diff --git a/pi4j-test/src/main/java/module-info.java b/pi4j-test/src/main/java/module-info.java
index 92627143..0377ef17 100644
--- a/pi4j-test/src/main/java/module-info.java
+++ b/pi4j-test/src/main/java/module-info.java
@@ -36,6 +36,19 @@
// Pi4J Mock Platform and Providers
requires com.pi4j.plugin.mock;
+
+ // TEST
+ requires com.pi4j.plugin.gpiod;
+ uses com.pi4j.plugin.gpiod.GpioDPlugin;
+ uses com.pi4j.plugin.gpiod.provider.gpio.digital.GpioDDigitalOutput;
+ uses com.pi4j.plugin.gpiod.provider.gpio.digital.GpioDDigitalOutputProvider;
+
+ requires com.pi4j.plugin.linuxfs;
+ uses com.pi4j.plugin.linuxfs.LinuxFsPlugin;
+ uses com.pi4j.plugin.linuxfs.provider.gpio.digital.LinuxFsDigitalOutput;
+ uses com.pi4j.plugin.linuxfs.provider.gpio.digital.LinuxFsDigitalOutputProvider;
+ // TEST END
+
uses com.pi4j.plugin.mock.platform.MockPlatform;
uses com.pi4j.plugin.mock.provider.gpio.analog.MockAnalogInput;
uses com.pi4j.plugin.mock.provider.gpio.analog.MockAnalogInputProvider;
diff --git a/plugins/pi4j-plugin-gpiod/.gitignore b/plugins/pi4j-plugin-gpiod/.gitignore
new file mode 100644
index 00000000..5ff6309b
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/.gitignore
@@ -0,0 +1,38 @@
+target/
+!.mvn/wrapper/maven-wrapper.jar
+!**/src/main/**/target/
+!**/src/test/**/target/
+
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+*.iws
+*.iml
+*.ipr
+
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/dist/
+/nbdist/
+/.nb-gradle/
+build/
+!**/src/main/**/build/
+!**/src/test/**/build/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
\ No newline at end of file
diff --git a/plugins/pi4j-plugin-gpiod/pom.xml b/plugins/pi4j-plugin-gpiod/pom.xml
new file mode 100644
index 00000000..466827b7
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/pom.xml
@@ -0,0 +1,113 @@
+
+
+
+ com.pi4j
+ pi4j-plugin
+ 2.4.0-SNAPSHOT
+ ../pi4j-plugin/pom.xml
+
+ 4.0.0
+
+
+ pi4j-plugin-gpiod
+ Pi4J :: PLUGIN :: GPIOD I/O Providers
+ Pi4J Library Plugin for GPIOD I/O Providers
+ jar
+
+
+ com.jcraft
+ jsch
+ ${jsch.version}
+
+
+ com.pi4j
+ pi4j-library-gpiod
+ ${project.version}
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+
+
+ org.slf4j
+ slf4j-simple
+ ${slf4j.version}
+ test
+
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+
+
+ copy-dependencies
+ process-sources
+
+ copy-dependencies
+
+
+ runtime
+ com.pi4j
+ ${project.build.directory}/dependencies
+ false
+ false
+ true
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-antrun-plugin
+
+
+
+
+ transfer-compiled-pi4j-jar
+ install
+
+ run
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/GpioDPlugin.java b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/GpioDPlugin.java
new file mode 100644
index 00000000..62fb9d66
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/GpioDPlugin.java
@@ -0,0 +1,60 @@
+package com.pi4j.plugin.gpiod;
+
+import com.pi4j.extension.Plugin;
+import com.pi4j.extension.PluginService;
+import com.pi4j.plugin.gpiod.provider.gpio.digital.GpioDDigitalOutputProvider;
+import com.pi4j.provider.Provider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * GpioDPlugin class.
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioDPlugin implements Plugin {
+
+ /**
+ * Constant NAME="GpioD"
+ */
+ public static final String NAME = "GpioD";
+ /**
+ * Constant ID="gpiod"
+ */
+ public static final String ID = "gpiod";
+
+ // Digital Output (GPIO) Provider name and unique ID
+ /**
+ * Constant DIGITAL_OUTPUT_PROVIDER_NAME="NAME + Digital Output (GPIO) Provider"
+ */
+ public static final String DIGITAL_OUTPUT_PROVIDER_NAME = NAME + " Digital Output (GPIO) Provider";
+ /**
+ * Constant DIGITAL_OUTPUT_PROVIDER_ID="ID + -digital-output"
+ */
+ public static final String DIGITAL_OUTPUT_PROVIDER_ID = ID + "-digital-output";
+
+ /**
+ * Constant DIGITAL_INPUT_PROVIDER_NAME="NAME + Digital Input (GPIO) Provider"
+ */
+ public static final String DIGITAL_INPUT_PROVIDER_NAME = NAME + " Digital Input (GPIO) Provider";
+ /**
+ * Constant DIGITAL_INPUT_PROVIDER_ID="ID + -digital-input"
+ */
+ public static final String DIGITAL_INPUT_PROVIDER_ID = ID + "-digital-input";
+
+
+ private Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void initialize(PluginService service) {
+ Provider[] providers = {
+ GpioDDigitalOutputProvider.newInstance()
+ };
+
+ service.register(providers);
+ }
+}
diff --git a/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/ActiveGpioChip.java b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/ActiveGpioChip.java
new file mode 100644
index 00000000..501960e4
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/ActiveGpioChip.java
@@ -0,0 +1,46 @@
+package com.pi4j.plugin.gpiod.provider.gpio.digital;
+
+import com.pi4j.library.gpiod.internal.GpioChip;
+import com.pi4j.library.gpiod.internal.GpioChipIterator;
+
+import java.io.Closeable;
+
+public class ActiveGpioChip implements Closeable {
+ private static GpioChip gpioChip;
+ private static int claimsOpen = 0;
+
+ public ActiveGpioChip() {
+ if(gpioChip == null) {
+ GpioChipIterator iterator = new GpioChipIterator();
+ GpioChip found = null;
+ while (iterator.hasNext()) {
+ GpioChip current = iterator.next();
+ if(current.getLabel().contains("pinctrl")) {
+ found = current;
+ iterator.noCloseCurrent();
+ break;
+ }
+ }
+ if(found == null) {
+ throw new IllegalStateException("Couldn't identify gpiochip!");
+ }
+ ActiveGpioChip.gpioChip = found;
+ }
+ ActiveGpioChip.claimsOpen += 1;
+ }
+
+ public GpioChip getGpioChip() {
+ return ActiveGpioChip.gpioChip;
+ }
+
+ public void close() {
+ ActiveGpioChip.claimsOpen -= 1;
+ if(ActiveGpioChip.claimsOpen == 0) {
+ ActiveGpioChip.gpioChip.close();
+ ActiveGpioChip.gpioChip = null;
+ } else if (ActiveGpioChip.claimsOpen < 0) {
+ ActiveGpioChip.claimsOpen = 0;
+ throw new IllegalStateException("ActiveGpioChip.chipsOpen < 0");
+ }
+ }
+}
diff --git a/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalInput.java b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalInput.java
new file mode 100644
index 00000000..f4c2d5a6
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalInput.java
@@ -0,0 +1,122 @@
+package com.pi4j.plugin.gpiod.provider.gpio.digital;
+
+import com.pi4j.context.Context;
+import com.pi4j.exception.InitializeException;
+import com.pi4j.exception.ShutdownException;
+import com.pi4j.io.gpio.digital.*;
+import com.pi4j.library.gpiod.internal.GpioD;
+import com.pi4j.library.gpiod.internal.GpioDException;
+import com.pi4j.library.gpiod.internal.GpioLine;
+import com.pi4j.library.gpiod.internal.GpioLineEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * PiGpioDigitalOutput class.
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioDDigitalInput extends DigitalInputBase implements DigitalInput {
+ private Logger logger = LoggerFactory.getLogger(this.getClass());
+ private final long inputMaxWaitNs = 500 * 1000 * 1000; // 0,5 seconds
+ protected ExecutorService executor = Executors.newSingleThreadExecutor(r -> new Thread(r, "Pi4J.GPIO.Monitor"));
+ private final GpioLine line;
+ private final long debounceNs;
+
+ /**
+ * Constructor for GpioDDigitalInput.
+ *
+ * @param line a {@link com.pi4j.library.gpiod.internal.GpioLine} object.
+ * @param provider a {@link DigitalInputProvider} object.
+ * @param config a {@link DigitalInputConfig} object.
+ */
+ public GpioDDigitalInput(GpioLine line, DigitalInputProvider provider, DigitalInputConfig config) {
+ super(provider, config);
+ this.line = line;
+ if(config.getDebounce() == 0) {
+ debounceNs = 0;
+ } else {
+ // Convert microseconds to nanoseconds
+ debounceNs = 1000 * config.getDebounce();
+ }
+ }
+
+ @Override
+ public DigitalInput initialize(Context context) throws InitializeException {
+ try {
+ switch (config.getPull()) {
+ case PULL_UP:
+ this.line.requestBothEdgeEventsFlags(config.getId(), GpioD.LINE_REQUEST_FLAG.BIAS_PULL_UP.getVal());
+ break;
+ case PULL_DOWN:
+ this.line.requestBothEdgeEventsFlags(config.getId(), GpioD.LINE_REQUEST_FLAG.BIAS_PULL_DOWN.getVal());
+ break;
+ case OFF:
+ this.line.requestBothEdgeEventsFlags(config.getId(), GpioD.LINE_REQUEST_FLAG.BIAS_DISABLE.getVal());
+ break;
+ }
+ } catch (GpioDException e) {
+ logger.error(e.getMessage(), e);
+ throw new InitializeException(e);
+ }
+ super.initialize(context);
+
+ Runnable monitorThread = new Runnable() {
+ @Override
+ public void run() {
+ DigitalState lastState = null;
+ while (true) {
+ long debounceNs = GpioDDigitalInput.this.debounceNs;
+ // We have to use this function before calling eventRead() directly, since native methods can't be interrupted.
+ // eventRead() is blocking and prevents thread interrupt while running
+ while (!GpioDDigitalInput.this.line.eventWait(inputMaxWaitNs)) {
+ continue;
+ }
+ GpioLineEvent lastEvent = GpioDDigitalInput.this.line.eventRead();
+ long currentTime = System.nanoTime();
+
+ // Perform debouncing
+ // If the event is too new to be sure that it is debounced then ...
+ while (lastEvent.getTimeNs() + debounceNs >= currentTime) {
+ // ... wait for remaining debounce time and watch out for new event(s)
+ if(GpioDDigitalInput.this.line.eventWait(Math.min(inputMaxWaitNs, lastEvent.getTimeNs() + debounceNs - currentTime))) {
+ // Repeat if a second event occurred withing debounce interval
+ lastEvent = GpioDDigitalInput.this.line.eventRead();
+ }
+
+ currentTime = System.nanoTime();
+ }
+
+ // Apply event only if the new state is not the same as the last state.
+ DigitalState newState = DigitalState.getState(lastEvent.getType() == GpioD.LINE_EVENT.RISING_EDGE);
+ if(lastState != newState) {
+ lastState = newState;
+ GpioDDigitalInput.this.dispatch(new DigitalStateChangeEvent(GpioDDigitalInput.this, newState));
+ }
+
+ }
+ }
+ };
+
+ executor.submit(monitorThread);
+ return this;
+ }
+
+ @Override
+ public DigitalInput shutdown(Context context) throws ShutdownException {
+ super.shutdown(context);
+ executor.shutdown();
+ this.line.release();
+ return this;
+ }
+
+ @Override
+ public DigitalState state() {
+ return DigitalState.getState(this.line.getValue());
+ }
+
+}
diff --git a/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalInputProvider.java b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalInputProvider.java
new file mode 100644
index 00000000..4adff7ec
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalInputProvider.java
@@ -0,0 +1,26 @@
+package com.pi4j.plugin.gpiod.provider.gpio.digital;
+
+import com.pi4j.io.gpio.digital.DigitalInputProvider;
+import com.pi4j.plugin.gpiod.GpioDPlugin;
+
+/**
+ * GpioDDigitalInputProvider interface.
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public interface GpioDDigitalInputProvider extends DigitalInputProvider {
+ /** Constant NAME="GpioDPlugin.DIGITAL_INPUT_PROVIDER_NAME"
*/
+ String NAME = GpioDPlugin.DIGITAL_INPUT_PROVIDER_NAME;
+ /** Constant ID="GpioDPlugin.DIGITAL_INPUT_PROVIDER_ID"
*/
+ String ID = GpioDPlugin.DIGITAL_INPUT_PROVIDER_ID;
+
+ /**
+ * newInstance.
+ *
+ * @return a {@link com.pi4j.plugin.gpiod.provider.gpio.digital.GpioDDigitalInputProvider} object.
+ */
+ static GpioDDigitalInputProvider newInstance() {
+ return new GpioDDigitalInputProviderImpl();
+ }
+}
diff --git a/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalInputProviderImpl.java b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalInputProviderImpl.java
new file mode 100644
index 00000000..5e4c69b0
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalInputProviderImpl.java
@@ -0,0 +1,49 @@
+package com.pi4j.plugin.gpiod.provider.gpio.digital;
+
+import com.pi4j.context.Context;
+import com.pi4j.exception.InitializeException;
+import com.pi4j.exception.ShutdownException;
+import com.pi4j.io.gpio.digital.*;
+import com.pi4j.library.gpiod.internal.GpioLine;
+
+public class GpioDDigitalInputProviderImpl extends DigitalInputProviderBase implements GpioDDigitalInputProvider {
+ private ActiveGpioChip chipClaim;
+
+ /**
+ * Constructor for GpioDDigitalInputProviderImpl.
+ */
+ public GpioDDigitalInputProviderImpl(){
+ this.id = ID;
+ this.name = NAME;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DigitalInput create(DigitalInputConfig config) {
+ // create new I/O instance based on I/O config
+ GpioLine line = this.chipClaim.getGpioChip().getLine(config.address());
+ return new GpioDDigitalInput(line, this, config);
+ }
+
+ @Override
+ public int getPriority() {
+ // GpioD should be used if available
+ return 150;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DigitalInputProvider initialize(Context context) throws InitializeException {
+ DigitalInputProvider provider = super.initialize(context);
+ this.chipClaim = new ActiveGpioChip();
+ return provider;
+ }
+
+ @Override
+ public DigitalInputProvider shutdown(Context context) throws ShutdownException {
+ if(chipClaim.getGpioChip() != null) {
+ this.chipClaim.close();
+ }
+ return super.shutdown(context);
+ }
+}
diff --git a/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalOutput.java b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalOutput.java
new file mode 100644
index 00000000..884c7e85
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalOutput.java
@@ -0,0 +1,94 @@
+package com.pi4j.plugin.gpiod.provider.gpio.digital;
+
+/*-
+ * #%L
+ * **********************************************************************
+ * ORGANIZATION : Pi4J
+ * PROJECT : Pi4J :: PLUGIN :: PIGPIO I/O Providers
+ * FILENAME : PiGpioDigitalOutput.java
+ *
+ * This file is part of the Pi4J project. More information about
+ * this project can be found here: https://pi4j.com/
+ * **********************************************************************
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+
+import com.pi4j.context.Context;
+import com.pi4j.exception.InitializeException;
+import com.pi4j.exception.ShutdownException;
+import com.pi4j.io.exception.IOException;
+import com.pi4j.io.gpio.digital.*;
+import com.pi4j.library.gpiod.internal.GpioDException;
+import com.pi4j.library.gpiod.internal.GpioLine;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * PiGpioDigitalOutput class.
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioDDigitalOutput extends DigitalOutputBase implements DigitalOutput {
+ private Logger logger = LoggerFactory.getLogger(this.getClass());
+ private final GpioLine line;
+
+ /**
+ * Constructor for GpioDDigitalOutput.
+ *
+ * @param line a {@link com.pi4j.library.gpiod.internal.GpioLine} object.
+ * @param provider a {@link DigitalOutputProvider} object.
+ * @param config a {@link DigitalOutputConfig} object.
+ */
+ public GpioDDigitalOutput(GpioLine line, DigitalOutputProvider provider, DigitalOutputConfig config) {
+ super(provider, config);
+ this.line = line;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DigitalOutput initialize(Context context) throws InitializeException {
+ try {
+ this.line.requestOutput(config.getId(), config.initialState().value().intValue());
+ } catch (GpioDException e) {
+ logger.error(e.getMessage(), e);
+ throw new InitializeException(e);
+ }
+ super.initialize(context);
+ return this;
+ }
+
+ @Override
+ public DigitalOutput shutdown(Context context) throws ShutdownException {
+ DigitalOutput returnMe = super.shutdown(context);
+ this.line.release();
+ return returnMe;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DigitalOutput state(DigitalState state) throws IOException {
+ try {
+ this.line.setValue(state.value().intValue());
+ } catch (GpioDException e) {
+ logger.error(e.getMessage(), e);
+ throw new IOException(e.getMessage(), e);
+ }
+ return super.state(state);
+ }
+}
diff --git a/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalOutputProvider.java b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalOutputProvider.java
new file mode 100644
index 00000000..1e4a681d
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalOutputProvider.java
@@ -0,0 +1,53 @@
+package com.pi4j.plugin.gpiod.provider.gpio.digital;
+
+/*
+ * #%L
+ * **********************************************************************
+ * ORGANIZATION : Pi4J
+ * PROJECT : Pi4J :: PLUGIN :: PIGPIO I/O Providers
+ * FILENAME : PiGpioDigitalOutputProvider.java
+ *
+ * This file is part of the Pi4J project. More information about
+ * this project can be found here: https://pi4j.com/
+ * **********************************************************************
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import com.pi4j.io.gpio.digital.DigitalOutputProvider;
+import com.pi4j.plugin.gpiod.GpioDPlugin;
+
+/**
+ * PiGpioDigitalOutputProvider interface.
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public interface GpioDDigitalOutputProvider extends DigitalOutputProvider {
+ /** Constant NAME="GpioDPlugin.DIGITAL_OUTPUT_PROVIDER_NA"{trunked}
*/
+ String NAME = GpioDPlugin.DIGITAL_OUTPUT_PROVIDER_NAME;
+ /** Constant ID="GpioDPlugin.DIGITAL_OUTPUT_PROVIDER_ID"
*/
+ String ID = GpioDPlugin.DIGITAL_OUTPUT_PROVIDER_ID;
+
+ /**
+ * newInstance.
+ *
+ * @return a {@link GpioDDigitalOutputProvider} object.
+ */
+ static GpioDDigitalOutputProvider newInstance() {
+ return new GpioDDigitalOutputProviderImpl();
+ }
+}
diff --git a/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalOutputProviderImpl.java b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalOutputProviderImpl.java
new file mode 100644
index 00000000..5e36c034
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/src/main/java/com/pi4j/plugin/gpiod/provider/gpio/digital/GpioDDigitalOutputProviderImpl.java
@@ -0,0 +1,89 @@
+package com.pi4j.plugin.gpiod.provider.gpio.digital;
+
+/*
+ * #%L
+ * **********************************************************************
+ * ORGANIZATION : Pi4J
+ * PROJECT : Pi4J :: PLUGIN :: PIGPIO I/O Providers
+ * FILENAME : PiGpioDigitalOutputProviderImpl.java
+ *
+ * This file is part of the Pi4J project. More information about
+ * this project can be found here: https://pi4j.com/
+ * **********************************************************************
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+
+import com.pi4j.context.Context;
+import com.pi4j.exception.InitializeException;
+import com.pi4j.exception.ShutdownException;
+import com.pi4j.io.gpio.digital.DigitalOutput;
+import com.pi4j.io.gpio.digital.DigitalOutputConfig;
+import com.pi4j.io.gpio.digital.DigitalOutputProvider;
+import com.pi4j.io.gpio.digital.DigitalOutputProviderBase;
+import com.pi4j.library.gpiod.internal.GpioChip;
+import com.pi4j.library.gpiod.internal.GpioChipIterator;
+import com.pi4j.library.gpiod.internal.GpioLine;
+
+
+/**
+ * PiGpioDigitalOutputProviderImpl class.
+ *
+ * @author Alexander Liggesmeyer (https://alexander.liggesmeyer.net/ )
+ * @version $Id: $Id
+ */
+public class GpioDDigitalOutputProviderImpl extends DigitalOutputProviderBase implements GpioDDigitalOutputProvider {
+ private ActiveGpioChip chipClaim;
+
+
+ /**
+ * Constructor for PiGpioDigitalOutputProviderImpl.
+ *
+ */
+ public GpioDDigitalOutputProviderImpl(){
+ this.id = ID;
+ this.name = NAME;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public DigitalOutput create(DigitalOutputConfig config) {
+ // create new I/O instance based on I/O config
+ GpioLine line = this.chipClaim.getGpioChip().getLine(config.address());
+ return new GpioDDigitalOutput(line, this, config);
+ }
+
+ @Override
+ public int getPriority() {
+ // GpioD should be used if available
+ return 150;
+ }
+
+ @Override
+ public DigitalOutputProvider initialize(Context context) throws InitializeException {
+ DigitalOutputProvider provider = super.initialize(context);
+ this.chipClaim = new ActiveGpioChip();
+ return provider;
+ }
+
+ @Override
+ public DigitalOutputProvider shutdown(Context context) throws ShutdownException {
+ if(chipClaim.getGpioChip() != null) {
+ this.chipClaim.close();
+ }
+ return super.shutdown(context);
+ }
+}
diff --git a/plugins/pi4j-plugin-gpiod/src/main/java/module-info.java b/plugins/pi4j-plugin-gpiod/src/main/java/module-info.java
new file mode 100644
index 00000000..841408cc
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/src/main/java/module-info.java
@@ -0,0 +1,43 @@
+import com.pi4j.plugin.gpiod.GpioDPlugin;
+
+/*-
+ * #%L
+ * **********************************************************************
+ * ORGANIZATION : Pi4J
+ * PROJECT : Pi4J :: PLUGIN :: LinuxFS I/O Providers
+ * FILENAME : module-info.java
+ *
+ * This file is part of the Pi4J project. More information about
+ * this project can be found here: https://pi4j.com/
+ * **********************************************************************
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Lesser Public License for more details.
+ *
+ * You should have received a copy of the GNU General Lesser Public
+ * License along with this program. If not, see
+ * .
+ * #L%
+ */
+module com.pi4j.plugin.gpiod {
+
+ // depends on SLF4J
+ requires org.slf4j;
+
+ requires com.pi4j;
+ requires com.pi4j.library.gpiod;
+ requires jsch;
+
+ exports com.pi4j.plugin.gpiod;
+ exports com.pi4j.plugin.gpiod.provider.gpio.digital;
+
+ provides com.pi4j.extension.Plugin
+ with GpioDPlugin;
+}
diff --git a/plugins/pi4j-plugin-gpiod/src/main/resources/services/com.pi4j.extension.Plugin b/plugins/pi4j-plugin-gpiod/src/main/resources/services/com.pi4j.extension.Plugin
new file mode 100644
index 00000000..e42965da
--- /dev/null
+++ b/plugins/pi4j-plugin-gpiod/src/main/resources/services/com.pi4j.extension.Plugin
@@ -0,0 +1 @@
+com.pi4j.plugin.gpiod.GpioDPlugin
\ No newline at end of file
diff --git a/plugins/pi4j-plugin/pom.xml b/plugins/pi4j-plugin/pom.xml
index 51b66a3c..6e41d6ea 100644
--- a/plugins/pi4j-plugin/pom.xml
+++ b/plugins/pi4j-plugin/pom.xml
@@ -31,6 +31,7 @@
../pi4j-plugin-pigpio
../pi4j-plugin-raspberrypi
../pi4j-plugin-linuxfs
+ ../pi4j-plugin-gpiod
diff --git a/pom.xml b/pom.xml
index 8d209a86..f8aa888c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -291,6 +291,20 @@
${pi4j.gpg.key}
+
+
+ com.pi4j.test/com.pi4j.test.GpiodTest
+
+
+
+
+ cocktailpi.local
+ 22
+ pi
+ raspberry
+ /home/pi/deploy
+
+