From 75a18afd119b235b30ae39b7757fac8a0e2fd22c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20=C3=96hrstr=C3=B6m?= Date: Sat, 8 Jan 2022 14:10:05 +0100 Subject: [PATCH] Add translate function. --- Makefile | 99 ++++++++------------------------------------ src/testinternals.cc | 69 ++++++++++++++++++++++++++++++ src/translatebits.cc | 99 ++++++++++++++++++++++++++++++++++++++++++++ src/translatebits.h | 55 ++++++++++++++++++++++++ 4 files changed, 240 insertions(+), 82 deletions(-) create mode 100644 src/translatebits.cc create mode 100644 src/translatebits.h diff --git a/Makefile b/Makefile index f000468..fd82d36 100644 --- a/Makefile +++ b/Makefile @@ -78,8 +78,8 @@ endif $(shell echo "#define VERSION \"$(VERSION)\"" > $(BUILD)/version.h.tmp) $(shell echo "#define COMMIT \"$(COMMIT_HASH)\"" >> $(BUILD)/version.h.tmp) -PREV_VERSION=$(shell cat -n $(BUILD)/version.h 2> /dev/null) -CURR_VERSION=$(shell cat -n $(BUILD)/version.h.tmp 2>/dev/null) +PREV_VERSION:=$(shell cat -n $(BUILD)/version.h 2> /dev/null) +CURR_VERSION:=$(shell cat -n $(BUILD)/version.h.tmp 2>/dev/null) ifneq ($(PREV_VERSION),$(CURR_VERSION)) $(shell mv $(BUILD)/version.h.tmp $(BUILD)/version.h) else @@ -105,7 +105,7 @@ $(BUILD)/%.o: src/%.cc $(wildcard src/%.h) $(CXX) $(CXXFLAGS) $< -c -E > $@.src $(CXX) $(CXXFLAGS) $< -MMD -c -o $@ -METER_OBJS:=\ +PROG_OBJS:=\ $(BUILD)/aes.o \ $(BUILD)/aescmac.o \ $(BUILD)/bus.o \ @@ -121,12 +121,10 @@ METER_OBJS:=\ $(BUILD)/shell.o \ $(BUILD)/sha256.o \ $(BUILD)/threads.o \ + $(BUILD)/translatebits.o \ $(BUILD)/util.o \ $(BUILD)/units.o \ $(BUILD)/wmbus.o \ - $(BUILD)/meter_auto.o \ - $(BUILD)/meter_unknown.o \ - $(BUILD)/meter_amiplus.o \ $(BUILD)/wmbus_amb8465.o \ $(BUILD)/wmbus_im871a.o \ $(BUILD)/wmbus_cul.o \ @@ -136,74 +134,11 @@ METER_OBJS:=\ $(BUILD)/wmbus_rawtty.o \ $(BUILD)/wmbus_rc1180.o \ $(BUILD)/wmbus_utils.o \ - $(BUILD)/meter_apator08.o \ - $(BUILD)/meter_apator162.o \ - $(BUILD)/meter_aventieswm.o \ - $(BUILD)/meter_aventieshca.o \ - $(BUILD)/meter_bfw240radio.o \ - $(BUILD)/meter_cma12w.o \ - $(BUILD)/meter_compact5.o \ - $(BUILD)/meter_dme_07.o \ - $(BUILD)/meter_ebzwmbe.o \ - $(BUILD)/meter_ehzp.o \ - $(BUILD)/meter_esyswm.o \ - $(BUILD)/meter_elf.o \ - $(BUILD)/meter_em24.o \ - $(BUILD)/meter_emerlin868.o \ - $(BUILD)/meter_ev200.o \ - $(BUILD)/meter_evo868.o \ - $(BUILD)/meter_eurisii.o \ - $(BUILD)/meter_fhkvdataiii.o \ - $(BUILD)/meter_fhkvdataiv.o \ - $(BUILD)/meter_flowiq2200.o \ - $(BUILD)/meter_hydrus.o \ - $(BUILD)/meter_hydrocalm3.o \ - $(BUILD)/meter_hydrodigit.o \ - $(BUILD)/meter_ei6500.o \ - $(BUILD)/meter_iperl.o \ - $(BUILD)/meter_izar.o \ - $(BUILD)/meter_izar3.o \ - $(BUILD)/meter_lansendw.o \ - $(BUILD)/meter_lansensm.o \ - $(BUILD)/meter_lansenth.o \ - $(BUILD)/meter_lansenpu.o \ - $(BUILD)/meter_lse_07_17.o \ - $(BUILD)/meter_minomess.o \ - $(BUILD)/meter_mkradio3.o \ - $(BUILD)/meter_mkradio4.o \ - $(BUILD)/meter_multical21.o \ - $(BUILD)/meter_multical302.o \ - $(BUILD)/meter_multical403.o \ - $(BUILD)/meter_multical602.o \ - $(BUILD)/meter_multical603.o \ - $(BUILD)/meter_multical803.o \ - $(BUILD)/meter_omnipower.o \ - $(BUILD)/meter_piigth.o \ - $(BUILD)/meter_q400.o \ - $(BUILD)/meter_qcaloric.o \ - $(BUILD)/meter_qheat.o \ - $(BUILD)/meter_qsmoke.o \ - $(BUILD)/meter_rfmamb.o \ - $(BUILD)/meter_rfmtx1.o \ - $(BUILD)/meter_sharky.o \ - $(BUILD)/meter_sharky774.o \ - $(BUILD)/meter_supercom587.o \ - $(BUILD)/meter_sontex868.o \ - $(BUILD)/meter_topaseskr.o \ - $(BUILD)/meter_tsd2.o \ - $(BUILD)/meter_ultrimis.o \ - $(BUILD)/meter_vario451.o \ - $(BUILD)/meter_waterstarm.o \ - $(BUILD)/meter_whe46x.o \ - $(BUILD)/meter_whe5x.o \ - $(BUILD)/meter_sensostar.o \ - $(BUILD)/meter_gransystems_ccx01.o \ - $(BUILD)/meter_lse_08.o \ - $(BUILD)/meter_weh_07.o \ - $(BUILD)/meter_unismart.o \ - $(BUILD)/meter_munia.o \ +DRIVER_OBJS:=$(wildcard src/meter_*.cc) +DRIVER_OBJS:=$(patsubst src/%.cc,$(BUILD)/%.o,$(DRIVER_OBJS)) + all: $(BUILD)/wmbusmeters $(BUILD)/wmbusmetersd $(BUILD)/wmbusmeters.g $(BUILD)/wmbusmeters-admin $(BUILD)/testinternals deb: wmbusmeters_$(DEBVERSION)_$(DEBARCH).deb @@ -242,8 +177,8 @@ snapcraft: $(BUILD)/main.o: $(BUILD)/short_manual.h $(BUILD)/version.h # Build binary with debug information. ~15M size binary. -$(BUILD)/wmbusmeters.g: $(METER_OBJS) $(BUILD)/main.o $(BUILD)/short_manual.h - $(CXX) -o $(BUILD)/wmbusmeters.g $(METER_OBJS) $(BUILD)/main.o $(LDFLAGS) -lrtlsdr $(USBLIB) -lpthread +$(BUILD)/wmbusmeters.g: $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/main.o $(BUILD)/short_manual.h + $(CXX) -o $(BUILD)/wmbusmeters.g $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/main.o $(LDFLAGS) -lrtlsdr $(USBLIB) -lpthread # Production build will have debug information stripped. ~1.5M size binary. # DEBUG=true builds, which has address sanitizer code, will always keep the debug information. @@ -258,8 +193,8 @@ ifeq ($(shell uname -s),Darwin) $(BUILD)/wmbusmeters-admin: touch $(BUILD)/wmbusmeters-admin else -$(BUILD)/wmbusmeters-admin: $(METER_OBJS) $(BUILD)/admin.o $(BUILD)/ui.o $(BUILD)/short_manual.h - $(CXX) -o $(BUILD)/wmbusmeters-admin.g $(METER_OBJS) $(BUILD)/admin.o $(BUILD)/ui.o $(LDFLAGS) -lmenu -lform -lncurses -lrtlsdr $(USBLIB) -lpthread +$(BUILD)/wmbusmeters-admin: $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/admin.o $(BUILD)/ui.o $(BUILD)/short_manual.h + $(CXX) -o $(BUILD)/wmbusmeters-admin.g $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/admin.o $(BUILD)/ui.o $(LDFLAGS) -lmenu -lform -lncurses -lrtlsdr $(USBLIB) -lpthread endif $(BUILD)/short_manual.h: README.md @@ -269,11 +204,11 @@ $(BUILD)/short_manual.h: README.md | grep -v '```' >> $(BUILD)/short_manual.h echo ')MANUAL";' >> $(BUILD)/short_manual.h -$(BUILD)/testinternals: $(METER_OBJS) $(BUILD)/testinternals.o - $(CXX) -o $(BUILD)/testinternals $(METER_OBJS) $(BUILD)/testinternals.o $(LDFLAGS) -lrtlsdr $(USBLIB) -lpthread +$(BUILD)/testinternals: $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/testinternals.o + $(CXX) -o $(BUILD)/testinternals $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/testinternals.o $(LDFLAGS) -lrtlsdr $(USBLIB) -lpthread -$(BUILD)/fuzz: $(METER_OBJS) $(BUILD)/fuzz.o - $(CXX) -o $(BUILD)/fuzz $(METER_OBJS) $(BUILD)/fuzz.o $(LDFLAGS) -lrtlsdr -lpthread +$(BUILD)/fuzz: $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/fuzz.o + $(CXX) -o $(BUILD)/fuzz $(PROG_OBJS) $(DRIVER_OBJS) $(BUILD)/fuzz.o $(LDFLAGS) -lrtlsdr -lpthread clean: rm -rf build/* build_arm/* build_debug/* build_arm_debug/* *~ @@ -286,7 +221,7 @@ clean_cc: # inside the build_debug where non-executed source lines are marked ##### gcov: @if [ "$(DEBUG)" = "" ]; then echo "You have to run \"make gcov DEBUG=true\""; exit 1; fi - $(GCOV) -o build_debug $(METER_OBJS) + $(GCOV) -o build_debug $(PROG_OBJS) $(DRIVER_OBJS) mv *.gcov build_debug lcov: @@ -395,4 +330,4 @@ relay: utils/relay.c gcc -g utils/relay.c -o relay -O0 -ggdb -fsanitize=address -fno-omit-frame-pointer -fprofile-arcs -ftest-coverage # Include dependency information generated by gcc in a previous compile. -include $(wildcard $(patsubst %.o,%.d,$(METER_OBJS))) +include $(wildcard $(patsubst %.o,%.d,$(PROG_OBJS) $(DRIVER_OBJS))) diff --git a/src/testinternals.cc b/src/testinternals.cc index 02d0133..59b3c23 100644 --- a/src/testinternals.cc +++ b/src/testinternals.cc @@ -22,6 +22,7 @@ #include"meters.h" #include"printer.h" #include"serial.h" +#include"translatebits.h" #include"util.h" #include"wmbus.h" #include"dvparser.h" @@ -43,6 +44,7 @@ void test_months(); void test_aes(); void test_sbc(); void test_hex(); +void test_translate(); int main(int argc, char **argv) { @@ -73,6 +75,7 @@ int main(int argc, char **argv) test_aes(); test_sbc(); test_hex(); + test_translate(); return 0; } @@ -1004,3 +1007,69 @@ void test_hex() test_is_hex("00112233445566778899AABBCCDDEEF", true, true); test_is_hex("00112233445566778899AABBCCDDEEFG", false, false); } + +void test_translate() +{ + Translate::Lookup lookup1 = + { + { + { + "ACCESS_BITS", + Translate::Type::BitToString, + 0xf0, + { + { 0x10, "NO_ACCESS" }, + { 0x20, "ALL_ACCESS" }, + { 0x40, "TEMP_ACCESS" }, + } + }, + { + "ACCESSOR_TYPE", + Translate::Type::IndexToString, + 0x0f, + { + { 0x00, "ACCESSOR_RED" }, + { 0x07, "ACCESSOR_GREEN" }, + }, + }, + }, + }; + + Translate::Lookup lookup2 = + { + { + { + "ERROR_FLAGS", + Translate::Type::BitToString, + 0x0f, + { + { 0x01, "BACKWARD_FLOW" }, + { 0x02, "DRY" }, + { 0x12, "TRIG" }, + } + }, + }, + }; + + string s, e; + s = lookup1.translate(0xA0); + e = "ALL_ACCESS UNKNOWN_ACCESS_BITS(0x80) ACCESSOR_RED"; + if (s != e) + { + printf("ERROR expected \"%s\" but got \"%s\"\n", e.c_str(), s.c_str()); + } + + s = lookup1.translate(0x35); + e = "NO_ACCESS ALL_ACCESS UNKNOWN_ACCESSOR_TYPE(0x5)"; + if (s != e) + { + printf("ERROR expected \"%s\" but got \"%s\"\n", e.c_str(), s.c_str()); + } + + s = lookup2.translate(0x02); + e = "DRY BAD_RULE_ERROR_FLAGS(from=0x12 mask=0xf)"; + if (s != e) + { + printf("ERROR expected \"%s\" but got \"%s\"\n", e.c_str(), s.c_str()); + } +} diff --git a/src/translatebits.cc b/src/translatebits.cc new file mode 100644 index 0000000..15e3e51 --- /dev/null +++ b/src/translatebits.cc @@ -0,0 +1,99 @@ +/* + Copyright (C) 2021 Fredrik Öhrström + + 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 + 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 Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include"translatebits.h" +#include"util.h" + +#include + +using namespace Translate; +using namespace std; + +void handleRule(Rule& rule, string &s, uint64_t bits) +{ + // Keep only the masked bits. + bits = bits & rule.mask; + + if (rule.type == Type::BitToString) + { + for (Map& m : rule.map) + { + if ((~rule.mask & m.from) != 0) + { + string tmp; + strprintf(tmp, "BAD_RULE_%s(from=0x%x mask=0x%x)", rule.name.c_str(), m.from, rule.mask); + s += tmp+" "; + } + uint64_t from = m.from & rule.mask; // Better safe than sorry. + if ((bits & from) != 0) + { + s += m.to+" "; + bits = bits & ~m.from; // Remove the handled bit. + } + } + if (bits != 0) + { + // Oups, there are bits that we have not handled.... + string tmp; + strprintf(tmp, "UNKNOWN_%s(0x%x)", rule.name.c_str(), bits); + s += tmp+" "; + } + } + else if (rule.type == Type::IndexToString) + { + bool found = false; + for (Map& m : rule.map) + { + if ((~rule.mask & m.from) != 0) + { + string tmp; + strprintf(tmp, "BAD_RULE_%s(from=0x%x mask=0x%x)", rule.name.c_str(), m.from, rule.mask); + s += tmp+" "; + } + uint64_t from = m.from & rule.mask; // Better safe than sorry. + if (bits == from) + { + s += m.to+" "; + found = true; + } + } + if (!found) + { + // Oups, this index has not been found. + string tmp; + strprintf(tmp, "UNKNOWN_%s(0x%x)", rule.name.c_str(), bits); + s += tmp+" "; + } + } + else + { + assert(0); + } +} + +string Lookup::translate(uint64_t bits) +{ + string s = ""; + + for (Rule& r : rules) + { + handleRule(r, s, bits); + } + + while (s.back() == ' ') s.pop_back(); + return s; +} diff --git a/src/translatebits.h b/src/translatebits.h new file mode 100644 index 0000000..a9000cd --- /dev/null +++ b/src/translatebits.h @@ -0,0 +1,55 @@ +/* + Copyright (C) 2021 Fredrik Öhrström + + 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 + 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 Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef TRANSLATEBITS_H +#define TRANSLATEBITS_H + +#include +#include +#include + +namespace Translate +{ + enum class Type + { + BitToString, + IndexToString + }; + + struct Map + { + uint64_t from; + std::string to; + }; + + struct Rule + { + std::string name; + Type type; + uint64_t mask; // Bits to be used are set as 1. + std::vector map; + }; + + struct Lookup + { + std::vector rules; + + std::string translate(uint64_t bits); + }; +}; + +#endif