Skip to content

Commit 129bcba

Browse files
committed
Dependency version bump. Property to indicate if this is a recognised
board. Improved handling of unknown boards, ability to provision via GPIO chip and line offset (#202).
1 parent cdb582d commit 129bcba

File tree

20 files changed

+288
-205
lines changed

20 files changed

+288
-205
lines changed

diozero-bom/pom.xml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -65,32 +65,32 @@
6565
<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
6666
<maven-assembly-plugin.version>3.7.1</maven-assembly-plugin.version>
6767
<maven-javadoc-plugin.version>3.6.3</maven-javadoc-plugin.version>
68-
<maven-jar-plugin.version>3.3.0</maven-jar-plugin.version>
69-
<maven-shade-plugin.version>3.5.2</maven-shade-plugin.version>
68+
<maven-jar-plugin.version>3.4.1</maven-jar-plugin.version>
69+
<maven-shade-plugin.version>3.5.3</maven-shade-plugin.version>
7070
<maven-source-plugin.version>3.3.1</maven-source-plugin.version>
71-
<maven-install-plugin.version>3.1.1</maven-install-plugin.version>
72-
<maven-deploy-plugin.version>3.1.1</maven-deploy-plugin.version>
73-
<maven-gpg-plugin.version>3.2.2</maven-gpg-plugin.version>
71+
<maven-install-plugin.version>3.1.2</maven-install-plugin.version>
72+
<maven-deploy-plugin.version>3.1.2</maven-deploy-plugin.version>
73+
<maven-gpg-plugin.version>3.2.4</maven-gpg-plugin.version>
7474
<maven-release-plugin.version>3.0.1</maven-release-plugin.version>
7575
<maven-surefire-plugin.version>3.2.5</maven-surefire-plugin.version>
7676

7777
<!-- Other plugins -->
78-
<nexus-staging-maven-plugin.version>1.6.13</nexus-staging-maven-plugin.version>
78+
<nexus-staging-maven-plugin.version>1.7.0</nexus-staging-maven-plugin.version>
7979
<license-maven-plugin.version>2.4.0</license-maven-plugin.version>
8080
<versions-maven-plugin.version>2.16.2</versions-maven-plugin.version>
81-
<exec-maven-plugin.version>3.2.0</exec-maven-plugin.version>
81+
<exec-maven-plugin.version>3.3.0</exec-maven-plugin.version>
8282
<eclipse.m2e.lifecycle-mapping.version>1.0.0</eclipse.m2e.lifecycle-mapping.version>
8383

8484
<!-- Libraries -->
8585
<tinylog.version>2.7.0</tinylog.version>
86-
<hipparchus.version>3.0</hipparchus.version>
86+
<hipparchus.version>3.1</hipparchus.version>
8787
<eclipse-paho-client-mqttv3.version>1.2.5</eclipse-paho-client-mqttv3.version>
88-
<google-gson.version>2.10.1</google-gson.version>
89-
<google-protobuf-java.version>3.25.2</google-protobuf-java.version>
90-
<netty.version>4.1.108.Final</netty.version>
91-
<grpc.version>1.63.0</grpc.version>
88+
<google-gson.version>2.11.0</google-gson.version>
89+
<google-protobuf-java.version>4.27.0</google-protobuf-java.version>
90+
<netty.version>4.1.110.Final</netty.version>
91+
<grpc.version>1.64.0</grpc.version>
9292
<junit.version>5.10.2</junit.version>
93-
<mockito.version>5.11.0</mockito.version>
93+
<mockito.version>5.12.0</mockito.version>
9494
</properties>
9595

9696
<!-- Prepare common library versions -->

diozero-core/src/main/java/com/diozero/internal/board/GenericLinuxArmBoardInfo.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public class GenericLinuxArmBoardInfo extends BoardInfo {
6161
private List<String> compatibility;
6262
private Properties mmapGpioClasses;
6363
private Optional<Map<String, Integer>> chipMapping;
64+
private boolean boardDefLoaded = false;
6465

6566
public GenericLinuxArmBoardInfo(LocalSystemInfo systemInfo) {
6667
this(systemInfo, systemInfo.getMake());
@@ -102,17 +103,21 @@ public void populateBoardPinInfo() {
102103
* ["hardkernel,odroid-c2", "amlogic,meson-gxbb"]
103104
*/
104105
for (String compat : compatibility) {
105-
boolean loaded = loadBoardPinInfoDefinition(compat.split(","));
106-
107-
if (loaded) {
106+
boardDefLoaded = loadBoardPinInfoDefinition(compat.split(","));
107+
if (boardDefLoaded) {
108108
break;
109109
}
110110
}
111111

112-
// Note that if this fails the GPIO character implementation in the device
112+
// Note that if this fails the GPIO chardev implementation in the device
113113
// factory will attempt to auto-populate (if enabled)
114114
}
115115

116+
@Override
117+
public boolean isRecognised() {
118+
return boardDefLoaded;
119+
}
120+
116121
protected boolean loadBoardPinInfoDefinition(String... compatibilityParts) {
117122
for (int i = 0; i < compatibilityParts.length; i++) {
118123
compatibilityParts[i] = compatibilityParts[i].trim();

diozero-core/src/main/java/com/diozero/internal/provider/builtin/DefaultDeviceFactory.java

Lines changed: 78 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ public void start() {
114114

115115
Logger.debug("Found {} GPIO chips", Integer.valueOf(chips.size()));
116116

117+
final boolean unknown_board = !board_info.isRecognised();
118+
117119
// Validate the data in BoardPinInfo
118120
if (board_info instanceof GenericLinuxArmBoardInfo) {
119121
board_info.getChipMapping()
@@ -123,7 +125,7 @@ public void start() {
123125
// Validate the board pin info matches the GPIO chip and line offsets
124126
Logger.debug("Validating BoardPinInfo against detected GPIO chip and line offsets...");
125127
board_info.getGpioPins().forEach(pin_info -> {
126-
GpioChip chip = chips.get(Integer.valueOf(pin_info.getChip()));
128+
final GpioChip chip = chips.get(Integer.valueOf(pin_info.getChip()));
127129
if (chip == null) {
128130
if (pin_info.getChip() != -1) {
129131
Logger.warn("No such chip for id {}", Integer.valueOf(pin_info.getChip()));
@@ -138,75 +140,7 @@ public void start() {
138140

139141
// Validate the GPIO chip and line offsets match those detected
140142
Logger.debug("Validating detected GPIO chip and line offsets against BoardPinInfo...");
141-
chips.values().forEach(chip -> {
142-
for (GpioLine gpio_line : chip.getLines()) {
143-
PinInfo pin_info = null;
144-
final String line_name = gpio_line.getName().trim();
145-
146-
// Try to find this GPIO in the board pin info by the assumed system name
147-
if (!line_name.isEmpty()) {
148-
pin_info = board_info.getByName(line_name);
149-
}
150-
151-
// If the pin couldn't be found for the assigned name try to find the pin info
152-
// by chip and line offset number
153-
if (pin_info == null) {
154-
// Note that getByChipAndLineOffset doesn't create missing entries
155-
pin_info = board_info.getByChipAndLineOffset(chip.getChipId(), gpio_line.getOffset())
156-
.orElse(null);
157-
}
158-
159-
// Finally, if still not found see if the name is in the format GPIOnn and
160-
// lookup by GPIO number
161-
if (pin_info == null && line_name.matches(GPIO_LINE_NUMBER_PATTERN)) {
162-
// Note that this isn't reliable - GPIO names are often missing or not in this
163-
// format
164-
// Note that the unknown / generic board info classes will create missing pin
165-
// info objects if you call getByGpioNumber - we don't want that to happen here
166-
pin_info = board_info.getGpios()
167-
.get(Integer.valueOf(line_name.replaceAll(GPIO_LINE_NUMBER_PATTERN, "$1")));
168-
}
169-
170-
// XXX This includes a bit of a hack to ignore pins with the name "NC" - the BBB
171-
// does this for quite a few pins which triggers the warning message
172-
if (pin_info == null && !line_name.isEmpty() && !line_name.equals("NC")
173-
&& !line_name.equals("-")) {
174-
Logger.debug("Detected GPIO line ({} {}-{}) that isn't configured in BoardPinInfo",
175-
line_name, Integer.valueOf(chip.getChipId()),
176-
Integer.valueOf(gpio_line.getOffset()));
177-
if (addUnconfiguredGpios) {
178-
// Add a new pin info to the board pin info
179-
int gpio_num;
180-
if (line_name.matches(GPIO_LINE_NUMBER_PATTERN)) {
181-
gpio_num = Integer.parseInt(line_name.replaceAll(GPIO_LINE_NUMBER_PATTERN, "$1"));
182-
} else {
183-
// Calculate the GPIO number
184-
gpio_num = chip.getLineOffset() + gpio_line.getOffset();
185-
}
186-
pin_info = board_info.addGpioPinInfo(gpio_num, line_name, PinInfo.NOT_DEFINED,
187-
PinInfo.DIGITAL_IN_OUT, chip.getChipId(), gpio_line.getOffset());
188-
Logger.debug("Added pin info {}", pin_info);
189-
}
190-
} else if (pin_info != null) {
191-
if (pin_info.getChip() != chip.getChipId()
192-
|| pin_info.getLineOffset() != gpio_line.getOffset()) {
193-
Logger.warn(
194-
"Configured pin chip and line offset ({}-{}) doesn't match that detected ({}-{}), line name '{}' - updating",
195-
Integer.valueOf(pin_info.getChip()), Integer.valueOf(pin_info.getLineOffset()),
196-
Integer.valueOf(chip.getChipId()), Integer.valueOf(gpio_line.getOffset()),
197-
gpio_line.getName());
198-
pin_info.setChip(chip.getChipId());
199-
pin_info.setLineOffset(gpio_line.getOffset());
200-
}
201-
202-
if (!line_name.isEmpty() && !pin_info.getName().equals(line_name)) {
203-
Logger.info("Configured pin name ({}) doesn't match that detected ({})",
204-
pin_info.getName(), line_name);
205-
// XXX What to do about it - update the board pin info? Just ignore for now.
206-
}
207-
}
208-
}
209-
});
143+
chips.values().forEach(chip -> loadChip(board_info, unknown_board, chip));
210144
} catch (IOException e) {
211145
throw new RuntimeIOException("Error initialising GPIO chips: " + e.getMessage(), e);
212146
}
@@ -235,6 +169,76 @@ public void start() {
235169
}
236170
}
237171

172+
private void loadChip(BoardInfo boardInfo, boolean unknownBoard, GpioChip chip) {
173+
for (GpioLine gpio_line : chip.getLines()) {
174+
PinInfo pin_info = null;
175+
final String line_name = gpio_line.getName().trim();
176+
177+
// Try to find this GPIO in the board pin info by the assumed system name
178+
if (!line_name.isEmpty()) {
179+
pin_info = boardInfo.getByName(line_name);
180+
}
181+
182+
// If the pin couldn't be found for the assigned name try to find the pin info
183+
// by chip and line offset number
184+
if (pin_info == null) {
185+
// Note that getByChipAndLineOffset doesn't create missing entries
186+
pin_info = boardInfo.getByChipAndLineOffset(chip.getChipId(), gpio_line.getOffset()).orElse(null);
187+
}
188+
189+
// Finally, if still not found see if the name is in the format GPIOnn and
190+
// lookup by GPIO number
191+
if (pin_info == null && line_name.matches(GPIO_LINE_NUMBER_PATTERN)) {
192+
// Note that this isn't reliable - GPIO names are often missing or not in this
193+
// format
194+
// Note that the unknown / generic board info classes will create missing pin
195+
// info objects if you call getByGpioNumber - we don't want that to happen here
196+
pin_info = boardInfo.getGpios()
197+
.get(Integer.valueOf(line_name.replaceAll(GPIO_LINE_NUMBER_PATTERN, "$1")));
198+
}
199+
200+
// XXX This includes a bit of a hack to ignore pins with the name "NC" - the BBB
201+
// does this for quite a few pins which triggers the warning message
202+
if (pin_info == null && !line_name.isEmpty() && !line_name.equals("NC") && !line_name.equals("-")) {
203+
Logger.debug("Detected GPIO line ({} {}-{}) that isn't configured in BoardPinInfo", line_name,
204+
Integer.valueOf(chip.getChipId()), Integer.valueOf(gpio_line.getOffset()));
205+
if (addUnconfiguredGpios || unknownBoard) {
206+
// Add a new pin info to the board pin info
207+
int gpio_num;
208+
if (line_name.matches(GPIO_LINE_NUMBER_PATTERN)) {
209+
gpio_num = Integer.parseInt(line_name.replaceAll(GPIO_LINE_NUMBER_PATTERN, "$1"));
210+
} else {
211+
// Calculate the GPIO number
212+
gpio_num = chip.getLineOffset() + gpio_line.getOffset();
213+
}
214+
int physical_pin = PinInfo.NOT_DEFINED;
215+
if (line_name.startsWith("PIN_")) {
216+
physical_pin = Integer.parseInt(line_name.substring("PIN_".length()));
217+
}
218+
pin_info = boardInfo.addGpioPinInfo(gpio_num, line_name, physical_pin, PinInfo.DIGITAL_IN_OUT,
219+
chip.getChipId(), gpio_line.getOffset());
220+
Logger.debug("Added {}", pin_info);
221+
}
222+
} else if (pin_info != null) {
223+
if (pin_info.getChip() != chip.getChipId() || pin_info.getLineOffset() != gpio_line.getOffset()) {
224+
Logger.warn(
225+
"Configured pin chip and line offset ({}-{}) doesn't match that detected ({}-{}), line name '{}' - updating",
226+
Integer.valueOf(pin_info.getChip()), Integer.valueOf(pin_info.getLineOffset()),
227+
Integer.valueOf(chip.getChipId()), Integer.valueOf(gpio_line.getOffset()),
228+
gpio_line.getName());
229+
pin_info.setChip(chip.getChipId());
230+
pin_info.setLineOffset(gpio_line.getOffset());
231+
}
232+
233+
if (!line_name.isEmpty() && !pin_info.getName().equals(line_name)) {
234+
Logger.info("Configured pin name ({}) doesn't match that detected ({})", pin_info.getName(),
235+
line_name);
236+
// XXX What to do about it - update the board pin info? Just ignore for now.
237+
}
238+
}
239+
}
240+
}
241+
238242
private static void updateChipIds(Map<Integer, GpioChip> chips, Map<String, Integer> chipMapping,
239243
BoardInfo boardInfo) {
240244
if (chips == null || chips.isEmpty()) {
@@ -261,7 +265,7 @@ public void shutdown() {
261265
Logger.trace("shutdown()");
262266

263267
if (chips != null) {
264-
chips.values().forEach(chip -> chip.close());
268+
chips.values().forEach(GpioChip::close);
265269
chips.clear();
266270
}
267271

@@ -312,6 +316,9 @@ public int getGpioValue(int gpio) {
312316
if (mmapGpio != null) {
313317
return mmapGpio.gpioRead(gpio) ? 1 : 0;
314318
}
319+
// TODO Use GpioChip to read the device and clean up afterwards - check how gpioget works
320+
// (sets top input)
321+
// https://github.com/brgl/libgpiod/blob/master/tools/gpioget.c
315322
return Diozero.UNKNOWN_VALUE;
316323
}
317324

diozero-core/src/main/java/com/diozero/internal/provider/builtin/gpio/GpioChip.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public class GpioChip extends GpioChipInfo implements AutoCloseable, GpioLineEve
6161
public static Map<Integer, GpioChip> openAllChips() throws IOException {
6262
LibraryLoader.loadSystemUtils();
6363

64-
Map<Integer, GpioChip> chips = Files.list(Paths.get("/dev"))
64+
final Map<Integer, GpioChip> chips = Files.list(Paths.get("/dev"))
6565
.filter(p -> p.getFileName().toString().startsWith("gpiochip"))
6666
.map(p -> NativeGpioDevice.openChip(p.toString())) //
6767
.filter(p -> p != null) // openChip will return null if it is unable to open the chip
@@ -74,10 +74,9 @@ public static Map<Integer, GpioChip> openAllChips() throws IOException {
7474
// Calculate the line offset for the chips
7575
// This allows GPIOs to be auto-detected as the GPIO number is chip offset +
7676
// line offset
77-
AtomicInteger offset = new AtomicInteger(0);
78-
chips.entrySet().stream().sorted(Map.Entry.comparingByKey()).forEach(entry -> {
79-
entry.getValue().setLineOffset(offset.getAndAdd(entry.getValue().getNumLines()));
80-
});
77+
final AtomicInteger offset = new AtomicInteger(0);
78+
chips.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(Map.Entry::getValue)
79+
.forEach(chip -> chip.setLineOffset(offset.getAndAdd(chip.getNumLines())));
8180

8281
return chips;
8382
}
@@ -91,7 +90,7 @@ public static List<GpioChipInfo> getChips() {
9190
public static GpioChip openChip(int chipNum) {
9291
LibraryLoader.loadSystemUtils();
9392

94-
return openChip("/dev/" + GPIO_CHIP_FILENAME_PREFIX + "/" + chipNum);
93+
return openChip("/dev/" + GPIO_CHIP_FILENAME_PREFIX + chipNum);
9594
}
9695

9796
public static GpioChip openChip(String chipDeviceFile) {

diozero-core/src/main/java/com/diozero/internal/spi/SerialDeviceFactoryInterface.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,18 +47,17 @@ public interface SerialDeviceFactoryInterface extends DeviceFactoryInterface {
4747
* @param parity Parity option
4848
* @param readBlocking Do read operations block?
4949
* @param minReadChars The minimum number of characters to read
50-
* @param readTimeoutMillis How long a read operation waits for data before
51-
* timing out. 0 == no timeout
50+
* @param readTimeoutMillis How long a read operation waits for data before timing out. 0
51+
* == no timeout
5252
* @return Serial device instance
5353
* @throws RuntimeIOException if an error occurs
5454
*/
5555
default InternalSerialDeviceInterface provisionSerialDevice(String deviceFilename, int baud,
5656
SerialDevice.DataBits dataBits, SerialDevice.StopBits stopBits, SerialDevice.Parity parity,
5757
boolean readBlocking, int minReadChars, int readTimeoutMillis) throws RuntimeIOException {
5858

59-
return registerDevice(()->createSerialKey(deviceFilename),
60-
(k)-> createSerialDevice(k, deviceFilename, baud, dataBits, stopBits, parity,
61-
readBlocking, minReadChars, readTimeoutMillis));
59+
return registerDevice(() -> createSerialKey(deviceFilename), key -> createSerialDevice(key, deviceFilename,
60+
baud, dataBits, stopBits, parity, readBlocking, minReadChars, readTimeoutMillis));
6261
}
6362

6463
InternalSerialDeviceInterface createSerialDevice(String key, String deviceFilename, int baud,

diozero-core/src/main/java/com/diozero/sbc/BoardInfo.java

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,11 @@
3434
import com.diozero.internal.spi.MmapGpioInterface;
3535

3636
/**
37-
* Information about the connected SBC. Note that the connected board instance
38-
* might be a remote device, e.g. connected via serial, Bluetooth or TCP/IP. The
39-
* BoardInfo instance for the connected device must be obtained by calling
37+
* Information about the connected SBC. Note that the connected board instance might be a
38+
* remote device, e.g. connected via serial, Bluetooth or TCP/IP. The BoardInfo instance
39+
* for the connected device must be obtained by calling
4040
* {@link com.diozero.internal.spi.NativeDeviceFactoryInterface#getBoardInfo()
41-
* getBoardInfo()} the on the
42-
* {@link com.diozero.internal.spi.NativeDeviceFactoryInterface
41+
* getBoardInfo()} the on the {@link com.diozero.internal.spi.NativeDeviceFactoryInterface
4342
* NativeDeviceFactoryInterface} instance returned from
4443
* {@link DeviceFactoryHelper#getNativeDeviceFactory()}.
4544
*/
@@ -63,11 +62,17 @@ public BoardInfo(String make, String model, int memoryKb, String osId, String os
6362
}
6463

6564
/**
66-
* Pin initialisation is done separately to the constructor since all known
67-
* BoardInfo instances get instantiated on startup by the Java ServiceLoader.
65+
* Pin initialisation is done separately to the constructor since all known BoardInfo
66+
* instances get instantiated on startup by the Java ServiceLoader.
6867
*/
6968
public abstract void populateBoardPinInfo();
7069

70+
public boolean isBiasControlSupported() {
71+
return false;
72+
}
73+
74+
public abstract boolean isRecognised();
75+
7176
/**
7277
* The make of the connected board, e.g. "Raspberry Pi"
7378
*
@@ -128,12 +133,10 @@ public boolean compareMakeAndModel(String make2, String model2) {
128133
}
129134

130135
/**
131-
* Instantiate the memory mapped GPIO interface for this board. Not that the
132-
* caller needs to call {@link MmapGpioInterface#initialise initialise} prior to
133-
* use.
136+
* Instantiate the memory mapped GPIO interface for this board. Not that the caller needs
137+
* to call {@link MmapGpioInterface#initialise initialise} prior to use.
134138
*
135-
* @return the MMAP GPIO interface implementation for this board, null if there
136-
* isn't one
139+
* @return the MMAP GPIO interface implementation for this board, null if there isn't one
137140
*/
138141
public MmapGpioInterface createMmapGpio() {
139142
return null;
@@ -143,8 +146,4 @@ public MmapGpioInterface createMmapGpio() {
143146
public String toString() {
144147
return "BoardInfo [make=" + make + ", model=" + model + ", memory=" + memoryKb + "]";
145148
}
146-
147-
public boolean isBiasControlSupported() {
148-
return false;
149-
}
150149
}

0 commit comments

Comments
 (0)