From fd3f1844cd6fab60d464a0a0f48f8daaa50548b8 Mon Sep 17 00:00:00 2001 From: Mark Nolan Date: Tue, 15 Sep 2026 12:24:37 +0100 Subject: [PATCH] DEV-1019 Treat an all-0xFF daughter-card ID as an invalid expansion board log-and-stream-common#129 makes Shimmer3 boards with no expansion-board EEPROM report their daughter-card ID as FF FF FF rather than 00 00 00. 0xFF is the established "unprogrammed" sentinel - generateExpBrdIdArrayEmpty() already pads all 16 bytes with it - but isExpansionBoardValid() only special-cased the all-zero triplet. The UNKNOWN (-1) and LOG_FILE (-2) guards cannot catch it either, since the byte-array parse masks with 0xFF. An unprogrammed board therefore reported itself as valid, so DialogExpansionBoardIdSelection pre-populated the SR-programming dialog with 255/255/255 instead of leaving the selection blank. Reject the all-0xFF triplet alongside the existing all-zero one. Only all three fields being 0xFF counts: SR255.1.0 is the "no expansion board" entry DatabaseManager synthesises for a Shimmer3, and it has to stay valid. The two other callers - DbDeviceDetails.isPlaybackSupported() and ManageAndProcessDataNode.isAllVerInfoAvailable() in Shimmer-Advance-API - both gate on this for hardware in LIST_OF_UNITS_WITH_EXP_BRDS. Both already saw false for these boards under the old firmware's zeros, so this restores their pre-DEV-1019 behaviour rather than changing it. Co-Authored-By: Claude Opus 5 --- .../ExpansionBoardDetails.java | 15 +++ .../API_00009_ExpansionBoardDetailsTest.java | 110 ++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 ShimmerDriver/src/test/java/com/shimmerresearch/driverUtilities/API_00009_ExpansionBoardDetailsTest.java diff --git a/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/ExpansionBoardDetails.java b/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/ExpansionBoardDetails.java index 506bad6de..e9a12b648 100644 --- a/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/ExpansionBoardDetails.java +++ b/ShimmerDriver/src/main/java/com/shimmerresearch/driverUtilities/ExpansionBoardDetails.java @@ -100,8 +100,23 @@ public String getBoardVerString(){ return ("SR" + mExpansionBoardId + "." + mExpansionBoardRev + "." + mExpansionBoardRevSpecial); } + /** + * Checks whether these details represent a real, programmed expansion board. + * + *

A Shimmer3 with no expansion board EEPROM fitted reads back as all 0x00 + * on older firmware and as all 0xFF from DEV-1019 onwards, so both triplets + * are rejected here. + * + *

Only an all-0xFF triplet is rejected - {@link HW_ID_SR_CODES#NONE} (255) + * remains a legitimate SR number when paired with a real revision, e.g. the + * SR255.1.0 synthesised for a Shimmer3 that is known to have no expansion + * board. + * + * @return true if the expansion board details are valid + */ public boolean isExpansionBoardValid(){ if(!(mExpansionBoardId==0 && mExpansionBoardRev==0 && mExpansionBoardRevSpecial==0) + && !(mExpansionBoardId==0xFF && mExpansionBoardRev==0xFF && mExpansionBoardRevSpecial==0xFF) && (mExpansionBoardId!=HW_ID_SR_CODES.UNKNOWN && mExpansionBoardRev!=HW_ID_SR_CODES.UNKNOWN && mExpansionBoardRevSpecial!=HW_ID_SR_CODES.UNKNOWN) && (mExpansionBoardId!=HW_ID_SR_CODES.LOG_FILE && mExpansionBoardRev!=HW_ID_SR_CODES.LOG_FILE && mExpansionBoardRevSpecial!=HW_ID_SR_CODES.LOG_FILE)){ return true; diff --git a/ShimmerDriver/src/test/java/com/shimmerresearch/driverUtilities/API_00009_ExpansionBoardDetailsTest.java b/ShimmerDriver/src/test/java/com/shimmerresearch/driverUtilities/API_00009_ExpansionBoardDetailsTest.java new file mode 100644 index 000000000..879ad4e42 --- /dev/null +++ b/ShimmerDriver/src/test/java/com/shimmerresearch/driverUtilities/API_00009_ExpansionBoardDetailsTest.java @@ -0,0 +1,110 @@ +package com.shimmerresearch.driverUtilities; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.logging.Logger; + +import org.junit.Test; + +import com.shimmerresearch.driverUtilities.ShimmerVerDetails.HW_ID_SR_CODES; + +/** + * Tests for {@link ExpansionBoardDetails#isExpansionBoardValid()}. + * + *

DEV-1019: a Shimmer3 with no expansion board EEPROM fitted used to report + * its daughter-card ID as all 0x00 and now reports all 0xFF, so both have to be + * treated as "no board details available". + * + * @author Mark Nolan + * + */ +public class API_00009_ExpansionBoardDetailsTest { + + private static final Logger logger = Logger.getLogger(API_00009_ExpansionBoardDetailsTest.class.getName()); + + /** An unprogrammed EEPROM reads back as 0xFF - the DEV-1019 firmware behaviour. */ + @Test + public void testAllFfIsInvalid() { + ExpansionBoardDetails expBrd = new ExpansionBoardDetails(0xFF, 0xFF, 0xFF); + assertFalse(expBrd.isExpansionBoardValid()); + logger.info("Executing testAllFfIsInvalid -> PASS"); + } + + /** The same board as read off the wire, where the bytes are masked with 0xFF. */ + @Test + public void testAllFfFromByteArrayIsInvalid() { + ExpansionBoardDetails expBrd = new ExpansionBoardDetails(new byte[]{(byte)0xFF, (byte)0xFF, (byte)0xFF}); + assertFalse(expBrd.isExpansionBoardValid()); + logger.info("Executing testAllFfFromByteArrayIsInvalid -> PASS"); + } + + /** The 16-byte array Consensys writes when clearing an expansion board's details. */ + @Test + public void testGeneratedEmptyArrayIsInvalid() { + ExpansionBoardDetails expBrd = new ExpansionBoardDetails(ExpansionBoardDetails.generateExpBrdIdArrayEmpty()); + assertFalse(expBrd.isExpansionBoardValid()); + logger.info("Executing testGeneratedEmptyArrayIsInvalid -> PASS"); + } + + /** Pre-DEV-1019 firmware, and older database rows, carry zeros for the same state. */ + @Test + public void testAllZerosIsInvalid() { + ExpansionBoardDetails expBrd = new ExpansionBoardDetails(0, 0, 0); + assertFalse(expBrd.isExpansionBoardValid()); + logger.info("Executing testAllZerosIsInvalid -> PASS"); + } + + /** Nothing read yet - the default state of the class. */ + @Test + public void testUnknownIsInvalid() { + ExpansionBoardDetails expBrd = new ExpansionBoardDetails(); + assertFalse(expBrd.isExpansionBoardValid()); + logger.info("Executing testUnknownIsInvalid -> PASS"); + } + + @Test + public void testLogFileIsInvalid() { + ExpansionBoardDetails expBrd = new ExpansionBoardDetails( + HW_ID_SR_CODES.LOG_FILE, HW_ID_SR_CODES.LOG_FILE, HW_ID_SR_CODES.LOG_FILE); + assertFalse(expBrd.isExpansionBoardValid()); + logger.info("Executing testLogFileIsInvalid -> PASS"); + } + + /** A real, programmed board stays valid. */ + @Test + public void testProgrammedBoardIsValid() { + ExpansionBoardDetails expBrd = new ExpansionBoardDetails(HW_ID_SR_CODES.EXP_BRD_EXG_UNIFIED, 4, 0); + assertTrue(expBrd.isExpansionBoardValid()); + logger.info("Executing testProgrammedBoardIsValid -> PASS"); + } + + @Test + public void testProgrammedBoardFromGeneratedArrayIsValid() { + ExpansionBoardDetails expBrd = new ExpansionBoardDetails( + ExpansionBoardDetails.generateExpBrdIdArray(HW_ID_SR_CODES.EXP_BRD_EXG_UNIFIED, 4, 0)); + assertTrue(expBrd.isExpansionBoardValid()); + logger.info("Executing testProgrammedBoardFromGeneratedArrayIsValid -> PASS"); + } + + /** + * Only an all-0xFF triplet is rejected. SR255.1.0 is the "this Shimmer3 has + * no expansion board" entry that the database layer synthesises, and it has + * to stay valid or playback and config review break for those recordings. + */ + @Test + public void testSrNoneWithRealRevisionIsValid() { + ExpansionBoardDetails expBrd = new ExpansionBoardDetails(HW_ID_SR_CODES.NONE, 1, 0); + assertTrue(expBrd.isExpansionBoardValid()); + logger.info("Executing testSrNoneWithRealRevisionIsValid -> PASS"); + } + + /** A single 0xFF field is not enough to invalidate a board with a real SR number. */ + @Test + public void testProgrammedBoardWithFfSpecialRevIsValid() { + ExpansionBoardDetails expBrd = new ExpansionBoardDetails(HW_ID_SR_CODES.EXP_BRD_EXG_UNIFIED, 4, 0xFF); + assertTrue(expBrd.isExpansionBoardValid()); + logger.info("Executing testProgrammedBoardWithFfSpecialRevIsValid -> PASS"); + } + +}