From ad186eaa9ded723e68b4ab226c71125fd493a693 Mon Sep 17 00:00:00 2001 From: Tuan Hoang Date: Thu, 22 Aug 2019 13:27:20 +0000 Subject: testing/libmodbus: fix endian test on s390x This has been fixed in a folk in 2016: https://github.com/synexxus/libmodbus/commit/a511768e7fe7ec52d7bae1d9ae04e33f87a59627 Upstream PR: https://github.com/stephane/libmodbus/pull/465 --- .../772a6e2d2249e34f460a072f6452349ae6b3b921.patch | 315 +++++++++++++++++++++ testing/libmodbus/APKBUILD | 9 +- 2 files changed, 321 insertions(+), 3 deletions(-) create mode 100644 testing/libmodbus/772a6e2d2249e34f460a072f6452349ae6b3b921.patch diff --git a/testing/libmodbus/772a6e2d2249e34f460a072f6452349ae6b3b921.patch b/testing/libmodbus/772a6e2d2249e34f460a072f6452349ae6b3b921.patch new file mode 100644 index 0000000000..1600f39cd4 --- /dev/null +++ b/testing/libmodbus/772a6e2d2249e34f460a072f6452349ae6b3b921.patch @@ -0,0 +1,315 @@ +From 772a6e2d2249e34f460a072f6452349ae6b3b921 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?SZ=20Lin=20=28=E6=9E=97=E4=B8=8A=E6=99=BA=29?= + +Date: Thu, 20 Dec 2018 13:35:31 +0800 +Subject: [PATCH] Fix float endianness issue on big endian architecture. + +It converts float values depending on what order they come in. + +This patch was modified from rm5248 [1] + +[1] https://github.com/synexxus/libmodbus/commit/a511768e7fe7ec52d7bae1d9ae04e33f87a59627 +--- + src/modbus-data.c | 110 ++++++++++++++++++++++++++++++++------- + tests/unit-test-client.c | 22 +++++--- + tests/unit-test.h.in | 41 +++++++++++++-- + 3 files changed, 141 insertions(+), 32 deletions(-) + +diff --git a/src/modbus-data.c b/src/modbus-data.c +index 38ff5c14..3dacc000 100644 +--- a/src/modbus-data.c ++++ b/src/modbus-data.c +@@ -123,9 +123,18 @@ float modbus_get_float_abcd(const uint16_t *src) + { + float f; + uint32_t i; ++ uint8_t a, b, c, d; + +- i = ntohl(((uint32_t)src[0] << 16) + src[1]); +- memcpy(&f, &i, sizeof(float)); ++ a = (src[0] >> 8) & 0xFF; ++ b = (src[0] >> 0) & 0xFF; ++ c = (src[1] >> 8) & 0xFF; ++ d = (src[1] >> 0) & 0xFF; ++ ++ i = (a << 24) | ++ (b << 16) | ++ (c << 8) | ++ (d << 0); ++ memcpy(&f, &i, 4); + + return f; + } +@@ -135,9 +144,18 @@ float modbus_get_float_dcba(const uint16_t *src) + { + float f; + uint32_t i; ++ uint8_t a, b, c, d; + +- i = ntohl(bswap_32((((uint32_t)src[0]) << 16) + src[1])); +- memcpy(&f, &i, sizeof(float)); ++ a = (src[0] >> 8) & 0xFF; ++ b = (src[0] >> 0) & 0xFF; ++ c = (src[1] >> 8) & 0xFF; ++ d = (src[1] >> 0) & 0xFF; ++ ++ i = (d << 24) | ++ (c << 16) | ++ (b << 8) | ++ (a << 0); ++ memcpy(&f, &i, 4); + + return f; + } +@@ -147,9 +165,18 @@ float modbus_get_float_badc(const uint16_t *src) + { + float f; + uint32_t i; ++ uint8_t a, b, c, d; + +- i = ntohl((uint32_t)(bswap_16(src[0]) << 16) + bswap_16(src[1])); +- memcpy(&f, &i, sizeof(float)); ++ a = (src[0] >> 8) & 0xFF; ++ b = (src[0] >> 0) & 0xFF; ++ c = (src[1] >> 8) & 0xFF; ++ d = (src[1] >> 0) & 0xFF; ++ ++ i = (b << 24) | ++ (a << 16) | ++ (d << 8) | ++ (c << 0); ++ memcpy(&f, &i, 4); + + return f; + } +@@ -159,9 +186,18 @@ float modbus_get_float_cdab(const uint16_t *src) + { + float f; + uint32_t i; ++ uint8_t a, b, c, d; + +- i = ntohl((((uint32_t)src[1]) << 16) + src[0]); +- memcpy(&f, &i, sizeof(float)); ++ a = (src[0] >> 8) & 0xFF; ++ b = (src[0] >> 0) & 0xFF; ++ c = (src[1] >> 8) & 0xFF; ++ d = (src[1] >> 0) & 0xFF; ++ ++ i = (c << 24) | ++ (d << 16) | ++ (a << 8) | ++ (b << 0); ++ memcpy(&f, &i, 4); + + return f; + } +@@ -176,50 +212,84 @@ float modbus_get_float(const uint16_t *src) + memcpy(&f, &i, sizeof(float)); + + return f; ++ + } + + /* Set a float to 4 bytes for Modbus w/o any conversion (ABCD) */ + void modbus_set_float_abcd(float f, uint16_t *dest) + { + uint32_t i; ++ uint8_t *out = (uint8_t*) dest; ++ uint8_t a, b, c, d; + + memcpy(&i, &f, sizeof(uint32_t)); +- i = htonl(i); +- dest[0] = (uint16_t)(i >> 16); +- dest[1] = (uint16_t)i; ++ a = (i >> 24) & 0xFF; ++ b = (i >> 16) & 0xFF; ++ c = (i >> 8) & 0xFF; ++ d = (i >> 0) & 0xFF; ++ ++ out[0] = a; ++ out[1] = b; ++ out[2] = c; ++ out[3] = d; + } + + /* Set a float to 4 bytes for Modbus with byte and word swap conversion (DCBA) */ + void modbus_set_float_dcba(float f, uint16_t *dest) + { + uint32_t i; ++ uint8_t *out = (uint8_t*) dest; ++ uint8_t a, b, c, d; + + memcpy(&i, &f, sizeof(uint32_t)); +- i = bswap_32(htonl(i)); +- dest[0] = (uint16_t)(i >> 16); +- dest[1] = (uint16_t)i; ++ a = (i >> 24) & 0xFF; ++ b = (i >> 16) & 0xFF; ++ c = (i >> 8) & 0xFF; ++ d = (i >> 0) & 0xFF; ++ ++ out[0] = d; ++ out[1] = c; ++ out[2] = b; ++ out[3] = a; ++ + } + + /* Set a float to 4 bytes for Modbus with byte swap conversion (BADC) */ + void modbus_set_float_badc(float f, uint16_t *dest) + { + uint32_t i; ++ uint8_t *out = (uint8_t*) dest; ++ uint8_t a, b, c, d; + + memcpy(&i, &f, sizeof(uint32_t)); +- i = htonl(i); +- dest[0] = (uint16_t)bswap_16(i >> 16); +- dest[1] = (uint16_t)bswap_16(i & 0xFFFF); ++ a = (i >> 24) & 0xFF; ++ b = (i >> 16) & 0xFF; ++ c = (i >> 8) & 0xFF; ++ d = (i >> 0) & 0xFF; ++ ++ out[0] = b; ++ out[1] = a; ++ out[2] = d; ++ out[3] = c; + } + + /* Set a float to 4 bytes for Modbus with word swap conversion (CDAB) */ + void modbus_set_float_cdab(float f, uint16_t *dest) + { + uint32_t i; ++ uint8_t *out = (uint8_t*) dest; ++ uint8_t a, b, c, d; + + memcpy(&i, &f, sizeof(uint32_t)); +- i = htonl(i); +- dest[0] = (uint16_t)i; +- dest[1] = (uint16_t)(i >> 16); ++ a = (i >> 24) & 0xFF; ++ b = (i >> 16) & 0xFF; ++ c = (i >> 8) & 0xFF; ++ d = (i >> 0) & 0xFF; ++ ++ out[0] = c; ++ out[1] = d; ++ out[2] = a; ++ out[3] = b; + } + + /* DEPRECATED - Set a float to 4 bytes in a sort of Modbus format! */ +diff --git a/tests/unit-test-client.c b/tests/unit-test-client.c +index fdf5c26e..4fa6495d 100644 +--- a/tests/unit-test-client.c ++++ b/tests/unit-test-client.c +@@ -27,6 +27,7 @@ int send_crafted_request(modbus_t *ctx, int function, + uint16_t max_value, uint16_t bytes, + int backend_length, int backend_offset); + int equal_dword(uint16_t *tab_reg, const uint32_t value); ++int is_memory_equal(const void *s1, const void *s2, size_t size); + + #define BUG_REPORT(_cond, _format, _args ...) \ + printf("\nLine %d: assertion error for '%s': " _format "\n", __LINE__, # _cond, ## _args) +@@ -40,6 +41,11 @@ int equal_dword(uint16_t *tab_reg, const uint32_t value); + } \ + }; + ++int is_memory_equal(const void *s1, const void *s2, size_t size) ++{ ++ return (memcmp(s1, s2, size) == 0); ++} ++ + int equal_dword(uint16_t *tab_reg, const uint32_t value) { + return ((tab_reg[0] == (value >> 16)) && (tab_reg[1] == (value & 0xFFFF))); + } +@@ -287,26 +293,26 @@ int main(int argc, char *argv[]) + /** FLOAT **/ + printf("1/4 Set/get float ABCD: "); + modbus_set_float_abcd(UT_REAL, tab_rp_registers); +- ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_ABCD), "FAILED Set float ABCD"); +- real = modbus_get_float_abcd(tab_rp_registers); ++ ASSERT_TRUE(is_memory_equal(tab_rp_registers, UT_IREAL_ABCD_SET, 4), "FAILED Set float ABCD"); ++ real = modbus_get_float_abcd(UT_IREAL_ABCD_GET); + ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL); + + printf("2/4 Set/get float DCBA: "); + modbus_set_float_dcba(UT_REAL, tab_rp_registers); +- ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_DCBA), "FAILED Set float DCBA"); +- real = modbus_get_float_dcba(tab_rp_registers); ++ ASSERT_TRUE(is_memory_equal(tab_rp_registers, UT_IREAL_DCBA_SET, 4), "FAILED Set float DCBA"); ++ real = modbus_get_float_dcba(UT_IREAL_DCBA_GET); + ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL); + + printf("3/4 Set/get float BADC: "); + modbus_set_float_badc(UT_REAL, tab_rp_registers); +- ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_BADC), "FAILED Set float BADC"); +- real = modbus_get_float_badc(tab_rp_registers); ++ ASSERT_TRUE(is_memory_equal(tab_rp_registers, UT_IREAL_BADC_SET, 4), "FAILED Set float BADC"); ++ real = modbus_get_float_badc(UT_IREAL_BADC_GET); + ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL); + + printf("4/4 Set/get float CDAB: "); + modbus_set_float_cdab(UT_REAL, tab_rp_registers); +- ASSERT_TRUE(equal_dword(tab_rp_registers, UT_IREAL_CDAB), "FAILED Set float CDAB"); +- real = modbus_get_float_cdab(tab_rp_registers); ++ ASSERT_TRUE(is_memory_equal(tab_rp_registers, UT_IREAL_CDAB_SET, 4), "FAILED Set float CDAB"); ++ real = modbus_get_float_cdab(UT_IREAL_CDAB_GET); + ASSERT_TRUE(real == UT_REAL, "FAILED (%f != %f)\n", real, UT_REAL); + + printf("\nAt this point, error messages doesn't mean the test has failed\n"); +diff --git a/tests/unit-test.h.in b/tests/unit-test.h.in +index dca826f4..4ffa254f 100644 +--- a/tests/unit-test.h.in ++++ b/tests/unit-test.h.in +@@ -56,12 +56,45 @@ const uint16_t UT_INPUT_REGISTERS_ADDRESS = 0x108; + const uint16_t UT_INPUT_REGISTERS_NB = 0x1; + const uint16_t UT_INPUT_REGISTERS_TAB[] = { 0x000A }; + ++/* ++ * This float value is 0x47F12000 (in big-endian format). ++ * In Little-endian(intel) format, it will be stored in memory as follows: ++ * 0x00 0x20 0xF1 0x47 ++ * ++ * You can check this with the following code: ++ ++ float fl = UT_REAL; ++ uint8_t *inmem = (uint8_t*)&fl; ++ int x; ++ for(x = 0; x < 4; x++){ ++ printf("0x%02X ", inmem[ x ]); ++ } ++ printf("\n"); ++ */ + const float UT_REAL = 123456.00; + +-const uint32_t UT_IREAL_ABCD = 0x0020F147; +-const uint32_t UT_IREAL_DCBA = 0x47F12000; +-const uint32_t UT_IREAL_BADC = 0x200047F1; +-const uint32_t UT_IREAL_CDAB = 0xF1470020; ++/* ++ * The following arrays assume that 'A' is the MSB, ++ * and 'D' is the LSB. ++ * Thus, the following is the case: ++ * A = 0x47 ++ * B = 0xF1 ++ * C = 0x20 ++ * D = 0x00 ++ * ++ * There are two sets of arrays: one to test that the setting is correct, ++ * the other to test that the getting is correct. ++ * Note that the 'get' values must be constants in processor-endianness, ++ * as libmodbus will convert all words to processor-endianness as they come in. ++ */ ++const uint8_t UT_IREAL_ABCD_SET[] = {0x47, 0xF1, 0x20, 0x00}; ++const uint16_t UT_IREAL_ABCD_GET[] = {0x47F1, 0x2000}; ++const uint8_t UT_IREAL_DCBA_SET[] = {0x00, 0x20, 0xF1, 0x47}; ++const uint16_t UT_IREAL_DCBA_GET[] = {0x0020, 0xF147}; ++const uint8_t UT_IREAL_BADC_SET[] = {0xF1, 0x47, 0x00, 0x20}; ++const uint16_t UT_IREAL_BADC_GET[] = {0xF147, 0x0020}; ++const uint8_t UT_IREAL_CDAB_SET[] = {0x20, 0x00, 0x47, 0xF1}; ++const uint16_t UT_IREAL_CDAB_GET[] = {0x2000, 0x47F1}; + + /* const uint32_t UT_IREAL_ABCD = 0x47F12000); + const uint32_t UT_IREAL_DCBA = 0x0020F147; diff --git a/testing/libmodbus/APKBUILD b/testing/libmodbus/APKBUILD index 0c3d85de31..d7e97efe51 100644 --- a/testing/libmodbus/APKBUILD +++ b/testing/libmodbus/APKBUILD @@ -2,10 +2,12 @@ # Maintainer: Oz Tiram pkgname=libmodbus pkgver=3.1.6 -pkgrel=0 +pkgrel=1 pkgdesc="Modbus library which supports RTU communication over a serial line or a TCP link" url="https://libmodbus.org/" -source="https://libmodbus.org/releases/libmodbus-$pkgver.tar.gz" +source="https://libmodbus.org/releases/libmodbus-$pkgver.tar.gz + 772a6e2d2249e34f460a072f6452349ae6b3b921.patch + " arch="all" license="LGPL-2.1-or-later" makedepends="linux-headers" @@ -27,4 +29,5 @@ check() { package() { make DESTDIR="$pkgdir" install } -sha512sums="2e39aea41b1cfb30239c3d8271c68841d645a44a15019090e2efd16979bde373c76532f992aa6a4587b95c65ed9829705f32e698e445df7c0e1d52d0d1165bce libmodbus-3.1.6.tar.gz" +sha512sums="2e39aea41b1cfb30239c3d8271c68841d645a44a15019090e2efd16979bde373c76532f992aa6a4587b95c65ed9829705f32e698e445df7c0e1d52d0d1165bce libmodbus-3.1.6.tar.gz +5ee0264175024b482b6f6efaf6cd7fcdb6eb4b77b98634944f760ce73d67b5d7e157672a4662b6fb52d93d40862f361045c87d3c93919f67778402ff09b8e89c 772a6e2d2249e34f460a072f6452349ae6b3b921.patch" -- cgit v1.2.3