lib: crc: add `crc8_rohc` for CRC-8/ROHC variant calculation

This commit introduces the `crc8_rohc` function to the CRC library,
implementing the CRC-8/ROHC (RObust Header Compression) variant.
This algorithm is widely used in networking protocols, which is commonly
found in modem subsystems.

Signed-off-by: Pisit Sawangvonganan <pisit@ndrsolution.com>
This commit is contained in:
Pisit Sawangvonganan 2024-10-05 18:10:12 +07:00 committed by Alberto Escolar
parent 339ba1a23d
commit ec5354cd80
4 changed files with 64 additions and 4 deletions

View File

@ -29,6 +29,7 @@ extern "C" {
* computation.
*/
#define CRC8_CCITT_INITIAL_VALUE 0xFF
#define CRC8_ROHC_INITIAL_VALUE 0xFF
/* Initial value expected to be used at the beginning of the OpenPGP CRC-24 computation. */
#define CRC24_PGP_INITIAL_VALUE 0x00B704CEU
@ -58,9 +59,10 @@ enum crc_type {
CRC4, /**< Use @ref crc4 */
CRC4_TI, /**< Use @ref crc4_ti */
CRC7_BE, /**< Use @ref crc7_be */
CRC8, /**< Use @ref crc8 */
CRC8, /**< Use @ref crc8 */
CRC8_CCITT, /**< Use @ref crc8_ccitt */
CRC16, /**< Use @ref crc16 */
CRC8_ROHC, /**< Use @ref crc8_rohc */
CRC16, /**< Use @ref crc16 */
CRC16_ANSI, /**< Use @ref crc16_ansi */
CRC16_CCITT, /**< Use @ref crc16_ccitt */
CRC16_ITU_T, /**< Use @ref crc16_itu_t */
@ -135,7 +137,7 @@ uint16_t crc16_reflect(uint16_t poly, uint16_t seed, const uint8_t *src, size_t
* @return The computed CRC8 value
*/
uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
bool reversed);
bool reversed);
/**
* @brief Compute the checksum of a buffer with polynomial 0x1021, reflecting
@ -274,6 +276,20 @@ uint32_t crc32_c(uint32_t crc, const uint8_t *data,
*/
uint8_t crc8_ccitt(uint8_t initial_value, const void *buf, size_t len);
/**
* @brief Compute ROHC variant of CRC 8
*
* ROHC (Robust Header Compression) variant of CRC 8.
* Uses 0x07 as the polynomial with reflection.
*
* @param initial_value Initial value for the CRC computation
* @param buf Input bytes for the computation
* @param len Length of the input in bytes
*
* @return The computed CRC8 value
*/
uint8_t crc8_rohc(uint8_t initial_value, const void *buf, size_t len);
/**
* @brief Compute the CRC-7 checksum of a buffer.
*
@ -322,7 +338,7 @@ uint8_t crc4_ti(uint8_t seed, const uint8_t *src, size_t len);
* @return The computed CRC4 value
*/
uint8_t crc4(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
bool reversed);
bool reversed);
/**
* @brief Generate an OpenPGP CRC-24 checksum as defined in RFC 4880 section 6.1.
@ -384,6 +400,8 @@ static inline uint32_t crc_by_type(enum crc_type type, const uint8_t *src, size_
return crc8(src, len, poly, seed, reflect);
case CRC8_CCITT:
return crc8_ccitt(seed, src, len);
case CRC8_ROHC:
return crc8_rohc(seed, src, len);
case CRC16:
if (reflect) {
return crc16_reflect(poly, seed, src, len);

View File

@ -13,6 +13,11 @@ static const uint8_t crc8_ccitt_small_table[16] = {
0x38, 0x3f, 0x36, 0x31, 0x24, 0x23, 0x2a, 0x2d
};
static const uint8_t crc8_rohc_small_table[16] = {
0x00, 0x1c, 0x38, 0x24, 0x70, 0x6c, 0x48, 0x54,
0xe0, 0xfc, 0xd8, 0xc4, 0x90, 0x8c, 0xa8, 0xb4
};
uint8_t crc8_ccitt(uint8_t val, const void *buf, size_t cnt)
{
size_t i;
@ -26,6 +31,19 @@ uint8_t crc8_ccitt(uint8_t val, const void *buf, size_t cnt)
return val;
}
uint8_t crc8_rohc(uint8_t val, const void *buf, size_t cnt)
{
size_t i;
const uint8_t *p = buf;
for (i = 0; i < cnt; i++) {
val ^= p[i];
val = (val >> 4) ^ crc8_rohc_small_table[val & 0x0f];
val = (val >> 4) ^ crc8_rohc_small_table[val & 0x0f];
}
return val;
}
uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
bool reversed)
{

View File

@ -24,6 +24,7 @@ static const char *const crc_types[] = {
[CRC7_BE] = "7_be",
[CRC8] = "8",
[CRC8_CCITT] = "8_ccitt",
[CRC8_ROHC] = "8_rohc",
[CRC16] = "16",
[CRC16_ANSI] = "16_ansi",
[CRC16_CCITT] = "16_ccitt",

View File

@ -187,6 +187,29 @@ ZTEST(crc, test_crc8_ccitt)
sizeof(test2)) == 0xFB, "pass", "fail");
}
ZTEST(crc, test_crc8_rohc)
{
uint8_t test0[] = { 0 };
uint8_t test1[] = { 'A' };
uint8_t test2[] = { '1', '2', '3', '4', '5', '6', '7', '8', '9' };
uint8_t test3[] = { 0x07, 0x3F }; /* GSM 07.10 example */
uint8_t test4[] = { 0x07, 0x3F, 0x89 }; /* GSM 07.10 example */
uint8_t test5[] = { 0x03, 0x3f, 0x01, 0x1c }; /* Our GSM 07.10 calc */
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test0,
sizeof(test0)) == 0xcf, "pass", "fail");
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test1,
sizeof(test1)) == 0x2e, "pass", "fail");
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test2,
sizeof(test2)) == 0xd0, "pass", "fail");
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test3,
sizeof(test3)) == 0x76, "pass", "fail");
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test4,
sizeof(test4)) == 0xcf, "pass", "fail");
zassert(crc8_rohc(CRC8_ROHC_INITIAL_VALUE, test5,
sizeof(test5)) == 0xcf, "pass", "fail");
}
ZTEST(crc, test_crc7_be)
{
uint8_t test0[] = { 0 };