diff --git a/CMakeLists.txt b/CMakeLists.txt index af00839..6bd1f0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,12 +41,13 @@ python_add_library(p05 # Add libraries add_library(crclib STATIC ${CMAKE_SOURCE_DIR}/src/e2e/crclib.c) +add_library(util STATIC ${CMAKE_SOURCE_DIR}/src/e2e/util.c) # Link against util target_link_libraries(crc PRIVATE crclib) target_link_libraries(p01 PRIVATE crclib) target_link_libraries(p02 PRIVATE crclib) -target_link_libraries(p04 PRIVATE crclib) +target_link_libraries(p04 PRIVATE crclib util) target_link_libraries(p05 PRIVATE crclib) install(TARGETS crc p01 p02 p04 p05 LIBRARY DESTINATION e2e) diff --git a/src/e2e/crclib.h b/src/e2e/crclib.h index 9f51865..5227340 100644 --- a/src/e2e/crclib.h +++ b/src/e2e/crclib.h @@ -2,8 +2,8 @@ # # SPDX-License-Identifier: MIT */ -#ifndef CRC_H -#define CRC_H +#ifndef CRCLIB_H +#define CRCLIB_H #include #include diff --git a/src/e2e/p04.c b/src/e2e/p04.c index b2da291..6c00894 100644 --- a/src/e2e/p04.c +++ b/src/e2e/p04.c @@ -9,20 +9,33 @@ #include #include "crclib.h" - -uint32_t compute_p04_crc(uint8_t *data_ptr, +#include "util.h" + +#define P04LENGTH_POS 0 +#define P04LENGTH_LEN 2 +#define P04COUNTER_POS 2 +#define P04COUNTER_LEN 2 +#define P04DATAID_POS 4 +#define P04DATAID_LEN 4 +#define P04CRC_POS 8 +#define P04CRC_LEN 4 +#define P04HEADER_LEN (P04LENGTH_LEN+P04COUNTER_LEN+P04DATAID_LEN+P04CRC_LEN) + +uint32_t compute_p04_crc(uint8_t *data_ptr, uint16_t length, uint16_t offset) { uint32_t crc; // bytes before crc bytes - uint32_t crc_offset = (uint32_t)(offset + 8u); + uint32_t crc_offset = (uint32_t)(offset + P04CRC_POS); crc = Crc_CalculateCRC32P4(data_ptr, crc_offset, CRC32P4_INITIAL_VALUE, true); // bytes after crc bytes, if any - if (offset + 12u < length){ - crc = Crc_CalculateCRC32P4(&data_ptr[crc_offset + 4u], (uint32_t)(length - (offset + 12u)), crc, false); + if (offset + P04HEADER_LEN < length){ + uint8_t * second_part_ptr = data_ptr + offset + P04HEADER_LEN; + uint32_t second_part_length = length - offset - P04HEADER_LEN; + crc = Crc_CalculateCRC32P4(second_part_ptr, second_part_length, crc, false); } return crc; } @@ -72,17 +85,17 @@ py_e2e_p04_protect(PyObject *module, PyErr_SetString(PyExc_ValueError, "\"data\" must be mutable. Use a bytearray or any object that implements the buffer protocol."); goto error; } - if (data.len < 12) + if (data.len < P04HEADER_LEN) { PyErr_SetString(PyExc_ValueError, "The length of bytearray \"data\" must be greater than or equal to 12."); goto error; } - if (length < 12 || length > data.len) + if (length < P04HEADER_LEN || length > data.len) { PyErr_SetString(PyExc_ValueError, "Parameter \"length\" must fulfill the following condition: 12 <= length <= len(data)."); goto error; } - if (offset > data.len - 12) + if (offset > data.len - P04HEADER_LEN) { PyErr_SetString(PyExc_ValueError, "Argument \"offset\" invalid."); goto error; @@ -91,29 +104,21 @@ py_e2e_p04_protect(PyObject *module, uint8_t *data_ptr = (uint8_t *)data.buf; // write length - data_ptr[offset] = (uint8_t)(length >> 8u); - data_ptr[offset + 1u] = (uint8_t)(length); + uint16_to_bigendian(data_ptr + offset + P04LENGTH_POS, length); // increment counter if (increment) { - uint16_t counter = ((uint16_t)(data_ptr[offset + 2u]) << 8u) + (uint16_t)(data_ptr[offset + 3u]); + uint16_t counter = bigendian_to_uint16(data_ptr + offset + P04COUNTER_POS); counter++; - data_ptr[offset + 2u] = (uint8_t)((counter >> 8u)); - data_ptr[offset + 3u] = (uint8_t)(counter & 0xFF); + uint16_to_bigendian(data_ptr + offset + P04COUNTER_POS, counter); } // write data_id - data_ptr[offset + 4u] = (uint8_t)(data_id >> 24u); - data_ptr[offset + 5u] = (uint8_t)(data_id >> 16u); - data_ptr[offset + 6u] = (uint8_t)(data_id >> 8u); - data_ptr[offset + 7u] = (uint8_t)(data_id); + uint32_to_bigendian(data_ptr + offset + P04DATAID_POS, data_id); // calculate CRC uint32_t crc = compute_p04_crc(data_ptr, length, offset); - data_ptr[offset + 8u] = (uint8_t)(crc >> 24u); - data_ptr[offset + 9u] = (uint8_t)(crc >> 16u); - data_ptr[offset + 10u] = (uint8_t)(crc >> 8u); - data_ptr[offset + 11u] = (uint8_t)(crc); + uint32_to_bigendian(data_ptr + offset + P04CRC_POS, crc); PyBuffer_Release(&data); @@ -162,17 +167,17 @@ py_e2e_p04_check(PyObject *module, { return NULL; } - if (data.len < 12) + if (data.len < P04HEADER_LEN) { - PyErr_SetString(PyExc_ValueError, "The length of bytearray \"data\" must be greater orequal to 12."); + PyErr_SetString(PyExc_ValueError, "The length of bytearray \"data\" must be greater or equal to 12."); goto error; } - if (length < 12 || length > data.len) + if (length < P04HEADER_LEN || length > data.len) { PyErr_SetString(PyExc_ValueError, "Parameter \"length\" must fulfill the following condition: 12 <= length <= len(data)."); goto error; } - if (offset > data.len - 12) + if (offset > data.len - P04HEADER_LEN) { PyErr_SetString(PyExc_ValueError, "Argument \"offset\" invalid."); goto error; @@ -181,23 +186,13 @@ py_e2e_p04_check(PyObject *module, uint8_t *data_ptr = (uint8_t *)data.buf; // read length - uint16_t length_actual = ( - ((uint16_t)(data_ptr[offset]) << 8u) - + (uint16_t)(data_ptr[offset + 1u])); + uint16_t length_actual = bigendian_to_uint16(data_ptr + offset + P04LENGTH_POS); // read data_id - uint32_t data_id_actual = ( - ((uint32_t)(data_ptr[offset + 4u]) << 24u) - + ((uint32_t)(data_ptr[offset + 5u]) << 16u) - + ((uint32_t)(data_ptr[offset + 6u]) << 8u) - + (uint32_t)(data_ptr[offset + 7u])); + uint32_t data_id_actual = bigendian_to_uint32(data_ptr + offset + P04DATAID_POS); // read crc - uint32_t crc_actual = ( - ((uint32_t)(data_ptr[offset + 8u]) << 24u) - + ((uint32_t)(data_ptr[offset + 9u]) << 16u) - + ((uint32_t)(data_ptr[offset + 10u]) << 8u) - + (uint32_t)(data_ptr[offset + 11u])); + uint32_t crc_actual = bigendian_to_uint32(data_ptr + offset + P04CRC_POS); // calculate CRC uint32_t crc = compute_p04_crc(data_ptr, length, offset); diff --git a/src/e2e/util.c b/src/e2e/util.c new file mode 100644 index 0000000..c8768d4 --- /dev/null +++ b/src/e2e/util.c @@ -0,0 +1,138 @@ +/* SPDX-FileCopyrightText: 2022-present Artur Drogunow +# +# SPDX-License-Identifier: MIT */ + +#include +#include + +// copy uint16_t into buffer in littleendian byte order +void uint16_to_littleendian(uint8_t *target, uint16_t value) +{ + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + target[i] = (uint8_t)((value >> (i * 8)) & 0xffu); + } +} + +// copy uint32_t into buffer in littleendian byte order +void uint32_to_littleendian(uint8_t *target, uint32_t value) +{ + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + target[i] = (uint8_t)((value >> (i * 8)) & 0xffu); + } +} + +// copy uint64_t into buffer in littleendian byte order +void uint64_to_littleendian(uint8_t *target, uint64_t value) +{ + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + target[i] = (uint8_t)((value >> (i * 8)) & 0xffu); + } +} + +// read uint16_t from littleendian byte order buffer +uint16_t littleendian_to_uint16(uint8_t *source) +{ + uint16_t value = 0; + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + value += (uint16_t)source[i] << (i * 8); + } + return value; +} + +// read uint32_t from littleendian byte order buffer +uint32_t littleendian_to_uint32(uint8_t *source) +{ + uint32_t value = 0; + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + value += (uint32_t)source[i] << (i * 8); + } + return value; +} + +// read uint64_t from littleendian byte order buffer +uint64_t littleendian_to_uint64(uint8_t *source) +{ + uint64_t value = 0; + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + value += (uint64_t)source[i] << (i * 8); + } + return value; +} + +// copy uint16_t into buffer in bigendian byte order +void uint16_to_bigendian(uint8_t *target, uint16_t value) +{ + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + target[i] = (uint8_t)((value >> ((len - 1 - i) * 8)) & 0xffu); + } +} + +// copy uint32_t into buffer in bigendian byte order +void uint32_to_bigendian(uint8_t *target, uint32_t value) +{ + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + target[i] = (uint8_t)((value >> ((len - 1 - i) * 8)) & 0xffu); + } +} + +// copy uint64_t into buffer in bigendian byte order +void uint64_to_bigendian(uint8_t *target, uint64_t value) +{ + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + target[i] = (uint8_t)((value >> ((len - 1 - i) * 8)) & 0xffu); + } +} + +// read uint16_t from bigendian byte order buffer +uint16_t bigendian_to_uint16(uint8_t *source) +{ + uint16_t value = 0; + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + value += (uint16_t)source[i] << ((len - 1 - i) * 8); + } + return value; +} + +// read uint32_t from bigendian byte order buffer +uint32_t bigendian_to_uint32(uint8_t *source) +{ + uint32_t value = 0; + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + value += (uint32_t)source[i] << ((len - 1 - i) * 8); + } + return value; +} + +// read uint64_t from bigendian byte order buffer +uint64_t bigendian_to_uint64(uint8_t *source) +{ + uint64_t value = 0; + size_t len = sizeof(value); + for (size_t i = 0; i < len; ++i) + { + value += (uint64_t)source[i] << ((len - 1 - i) * 8); + } + return value; +} diff --git a/src/e2e/util.h b/src/e2e/util.h new file mode 100644 index 0000000..c88ed73 --- /dev/null +++ b/src/e2e/util.h @@ -0,0 +1,26 @@ +/* SPDX-FileCopyrightText: 2022-present Artur Drogunow +# +# SPDX-License-Identifier: MIT */ + +#ifndef UTIL_H +#define UTIL_H + +#include + +void uint16_to_littleendian(uint8_t *target, uint16_t value); +void uint32_to_littleendian(uint8_t *target, uint32_t value); +void uint64_to_littleendian(uint8_t *target, uint64_t value); + +uint16_t littleendian_to_uint16(uint8_t *source); +uint32_t littleendian_to_uint32(uint8_t *source); +uint64_t littleendian_to_uint64(uint8_t *source); + +void uint16_to_bigendian(uint8_t *target, uint16_t value); +void uint32_to_bigendian(uint8_t *target, uint32_t value); +void uint64_to_bigendian(uint8_t *target, uint64_t value); + +uint16_t bigendian_to_uint16(uint8_t *source); +uint32_t bigendian_to_uint32(uint8_t *source); +uint64_t bigendian_to_uint64(uint8_t *source); + +#endif