From 91212df7c1bb75e33780bc3cc7c5655cb0f261f2 Mon Sep 17 00:00:00 2001 From: bmalinowsky Date: Sat, 3 Aug 2024 16:37:03 +0200 Subject: [PATCH] Workaround for ctrl bits issue with some usb sticks --- src/io/calimero/cemi/CEMIFactory.java | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/io/calimero/cemi/CEMIFactory.java b/src/io/calimero/cemi/CEMIFactory.java index f319eca8..14af55c6 100644 --- a/src/io/calimero/cemi/CEMIFactory.java +++ b/src/io/calimero/cemi/CEMIFactory.java @@ -1,6 +1,6 @@ /* Calimero 2 - A library for KNX network access - Copyright (c) 2006, 2023 B. Malinowsky + Copyright (c) 2006, 2024 B. Malinowsky This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,6 +36,9 @@ package io.calimero.cemi; +import static java.lang.System.Logger.Level.INFO; +import static java.lang.System.Logger.Level.WARNING; + import java.util.Arrays; import io.calimero.DataUnitBuilder; @@ -45,6 +48,7 @@ import io.calimero.KNXFormatException; import io.calimero.KNXIllegalArgumentException; import io.calimero.Priority; +import io.calimero.log.LogService; /** * Factory helper for creating and copying cEMI messages. @@ -53,6 +57,26 @@ */ public final class CEMIFactory { + // Workaround for some non spec-conform USB sticks, which sets some control bits when sending EMI frames. + // Those bits are reserved and shall be 0, but the USB stick requires them to not reject the frame. + private static final boolean setReservedEmiCtrlBits; + static { + final String pkg = "io.calimero.cemi"; + final String key = pkg + ".setReservedEmiCtrlBits"; + boolean value = false; + try { + final String prop = System.getProperty(key); + value = (prop != null && prop.isEmpty()) || Boolean.parseBoolean(prop); + if (value) + LogService.getLogger(pkg).log(INFO, "using {0}", key); + } + catch (final RuntimeException e) { + LogService.getLogger(pkg).log(WARNING, "on checking property " + key, e); + } + setReservedEmiCtrlBits = value; + } + + private CEMIFactory() {} /** @@ -324,6 +348,8 @@ public static byte[] toEmi(final int mc, final KNXAddress dst, final Priority p, buf[0] = (byte) mc; buf[1] = (byte) (p.value << 2); + if (setReservedEmiCtrlBits) + buf[1] |= (byte) 0xb0; // repeat flag is only relevant for .con final boolean rep = mc == Emi1_LData_con && repeat; final int ctrl = (rep ? 0x20 : 0) | (ackRequest ? 0x02 : 0) | (positiveCon ? 0 : 0x01);