LCOV - code coverage report
Current view: top level - zephyr/sys - crc.h Hit Total Coverage
Test: new.info Lines: 19 23 82.6 %
Date: 2024-12-22 00:14:23

          Line data    Source code
       1           1 : /*
       2             :  * Copyright (c) 2018 Workaround GmbH.
       3             :  * Copyright (c) 2017 Intel Corporation.
       4             :  * Copyright (c) 2017 Nordic Semiconductor ASA
       5             :  * Copyright (c) 2015 Runtime Inc
       6             :  * Copyright (c) 2018 Google LLC.
       7             :  * Copyright (c) 2022 Meta
       8             :  *
       9             :  * SPDX-License-Identifier: Apache-2.0
      10             :  */
      11             : /** @file
      12             :  * @brief CRC computation function
      13             :  */
      14             : 
      15             : #ifndef ZEPHYR_INCLUDE_SYS_CRC_H_
      16             : #define ZEPHYR_INCLUDE_SYS_CRC_H_
      17             : 
      18             : #include <zephyr/types.h>
      19             : #include <stdbool.h>
      20             : #include <stddef.h>
      21             : 
      22             : #include <zephyr/sys/__assert.h>
      23             : 
      24             : #ifdef __cplusplus
      25             : extern "C" {
      26             : #endif
      27             : 
      28             : /* Initial value expected to be used at the beginning of the crc8_ccitt
      29             :  * computation.
      30             :  */
      31           0 : #define CRC8_CCITT_INITIAL_VALUE 0xFF
      32           0 : #define CRC8_ROHC_INITIAL_VALUE  0xFF
      33             : 
      34             : /* Initial value expected to be used at the beginning of the OpenPGP CRC-24 computation. */
      35           0 : #define CRC24_PGP_INITIAL_VALUE 0x00B704CEU
      36             : /*
      37             :  * The CRC-24 value is stored on a 32-bit value, only the 3 least significant bytes
      38             :  * are meaningful. Use the following mask to only keep the CRC-24 value.
      39             :  */
      40           0 : #define CRC24_FINAL_VALUE_MASK 0x00FFFFFFU
      41             : 
      42             : /**
      43             :  * @defgroup checksum Checksum
      44             :  * @ingroup os_services
      45             :  */
      46             : 
      47             : /**
      48             :  * @defgroup crc CRC
      49             :  * @ingroup checksum
      50             :  * @{
      51             :  */
      52             : 
      53             : /**
      54             :  * @brief CRC algorithm enumeration
      55             :  *
      56             :  * These values should be used with the @ref crc dispatch function.
      57             :  */
      58           1 : enum crc_type {
      59             :         CRC4,        /**< Use @ref crc4 */
      60             :         CRC4_TI,     /**< Use @ref crc4_ti */
      61             :         CRC7_BE,     /**< Use @ref crc7_be */
      62             :         CRC8,        /**< Use @ref crc8 */
      63             :         CRC8_CCITT,  /**< Use @ref crc8_ccitt */
      64             :         CRC8_ROHC,   /**< Use @ref crc8_rohc */
      65             :         CRC16,       /**< Use @ref crc16 */
      66             :         CRC16_ANSI,  /**< Use @ref crc16_ansi */
      67             :         CRC16_CCITT, /**< Use @ref crc16_ccitt */
      68             :         CRC16_ITU_T, /**< Use @ref crc16_itu_t */
      69             :         CRC24_PGP,   /**< Use @ref crc24_pgp */
      70             :         CRC32_C,     /**< Use @ref crc32_c */
      71             :         CRC32_IEEE,  /**< Use @ref crc32_ieee */
      72             : };
      73             : 
      74             : /**
      75             :  * @brief Generic function for computing a CRC-16 without input or output
      76             :  *        reflection.
      77             :  *
      78             :  * Compute CRC-16 by passing in the address of the input, the input length
      79             :  * and polynomial used in addition to the initial value. This is O(n*8) where n
      80             :  * is the length of the buffer provided. No reflection is performed.
      81             :  *
      82             :  * @note If you are planning to use a CRC based on poly 0x1012 the functions
      83             :  * crc16_itu_t() is faster and thus recommended over this one.
      84             :  *
      85             :  * @param poly The polynomial to use omitting the leading x^16
      86             :  *             coefficient
      87             :  * @param seed Initial value for the CRC computation
      88             :  * @param src Input bytes for the computation
      89             :  * @param len Length of the input in bytes
      90             :  *
      91             :  * @return The computed CRC16 value (without any XOR applied to it)
      92             :  */
      93           1 : uint16_t crc16(uint16_t poly, uint16_t seed, const uint8_t *src, size_t len);
      94             : 
      95             : /**
      96             :  * @brief Generic function for computing a CRC-16 with input and output
      97             :  *        reflection.
      98             :  *
      99             :  * Compute CRC-16 by passing in the address of the input, the input length
     100             :  * and polynomial used in addition to the initial value. This is O(n*8) where n
     101             :  * is the length of the buffer provided. Both input and output are reflected.
     102             :  *
     103             :  * @note If you are planning to use a CRC based on poly 0x1012 the function
     104             :  * crc16_ccitt() is faster and thus recommended over this one.
     105             :  *
     106             :  * The following checksums can, among others, be calculated by this function,
     107             :  * depending on the value provided for the initial seed and the value the final
     108             :  * calculated CRC is XORed with:
     109             :  *
     110             :  * - CRC-16/ANSI, CRC-16/MODBUS, CRC-16/USB, CRC-16/IBM
     111             :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-modbus
     112             :  *   poly: 0x8005 (0xA001) initial seed: 0xffff, xor output: 0x0000
     113             :  *
     114             :  * @param poly The polynomial to use omitting the leading x^16
     115             :  *             coefficient. Important: please reflect the poly. For example,
     116             :  *             use 0xA001 instead of 0x8005 for CRC-16-MODBUS.
     117             :  * @param seed Initial value for the CRC computation
     118             :  * @param src Input bytes for the computation
     119             :  * @param len Length of the input in bytes
     120             :  *
     121             :  * @return The computed CRC16 value (without any XOR applied to it)
     122             :  */
     123           1 : uint16_t crc16_reflect(uint16_t poly, uint16_t seed, const uint8_t *src, size_t len);
     124             : /**
     125             :  * @brief Generic function for computing CRC 8
     126             :  *
     127             :  * Compute CRC 8 by passing in the address of the input, the input length
     128             :  * and polynomial used in addition to the initial value.
     129             :  *
     130             :  * @param src Input bytes for the computation
     131             :  * @param len Length of the input in bytes
     132             :  * @param polynomial The polynomial to use omitting the leading x^8
     133             :  *        coefficient
     134             :  * @param initial_value Initial value for the CRC computation
     135             :  * @param reversed Should we use reflected/reversed values or not
     136             :  *
     137             :  * @return The computed CRC8 value
     138             :  */
     139           1 : uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
     140             :              bool reversed);
     141             : 
     142             : /**
     143             :  * @brief Compute the checksum of a buffer with polynomial 0x1021, reflecting
     144             :  *        input and output.
     145             :  *
     146             :  * This function is able to calculate any CRC that uses 0x1021 as it polynomial
     147             :  * and requires reflecting both the input and the output. It is a fast variant
     148             :  * that runs in O(n) time, where n is the length of the input buffer.
     149             :  *
     150             :  * The following checksums can, among others, be calculated by this function,
     151             :  * depending on the value provided for the initial seed and the value the final
     152             :  * calculated CRC is XORed with:
     153             :  *
     154             :  * - CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-16/KERMIT
     155             :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-kermit
     156             :  *   initial seed: 0x0000, xor output: 0x0000
     157             :  *
     158             :  * - CRC-16/X-25, CRC-16/IBM-SDLC, CRC-16/ISO-HDLC
     159             :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-ibm-sdlc
     160             :  *   initial seed: 0xffff, xor output: 0xffff
     161             :  *
     162             :  * @note To calculate the CRC across non-contiguous blocks use the return
     163             :  *       value from block N-1 as the seed for block N.
     164             :  *
     165             :  * See ITU-T Recommendation V.41 (November 1988).
     166             :  *
     167             :  * @param seed Value to seed the CRC with
     168             :  * @param src Input bytes for the computation
     169             :  * @param len Length of the input in bytes
     170             :  *
     171             :  * @return The computed CRC16 value (without any XOR applied to it)
     172             :  */
     173           1 : uint16_t crc16_ccitt(uint16_t seed, const uint8_t *src, size_t len);
     174             : 
     175             : /**
     176             :  * @brief Compute the checksum of a buffer with polynomial 0x1021, no
     177             :  *        reflection of input or output.
     178             :  *
     179             :  * This function is able to calculate any CRC that uses 0x1021 as it polynomial
     180             :  * and requires no reflection on  both the input and the output. It is a fast
     181             :  * variant that runs in O(n) time, where n is the length of the input buffer.
     182             :  *
     183             :  * The following checksums can, among others, be calculated by this function,
     184             :  * depending on the value provided for the initial seed and the value the final
     185             :  * calculated CRC is XORed with:
     186             :  *
     187             :  * - CRC-16/XMODEM, CRC-16/ACORN, CRC-16/LTE
     188             :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-xmodem
     189             :  *   initial seed: 0x0000, xor output: 0x0000
     190             :  *
     191             :  * - CRC16/CCITT-FALSE, CRC-16/IBM-3740, CRC-16/AUTOSAR
     192             :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-ibm-3740
     193             :  *   initial seed: 0xffff, xor output: 0x0000
     194             :  *
     195             :  * - CRC-16/GSM
     196             :  *   https://reveng.sourceforge.io/crc-catalogue/16.htm#crc.cat.crc-16-gsm
     197             :  *   initial seed: 0x0000, xor output: 0xffff
     198             :  *
     199             :  * @note To calculate the CRC across non-contiguous blocks use the return
     200             :  *       value from block N-1 as the seed for block N.
     201             :  *
     202             :  * See ITU-T Recommendation V.41 (November 1988) (MSB first).
     203             :  *
     204             :  * @param seed Value to seed the CRC with
     205             :  * @param src Input bytes for the computation
     206             :  * @param len Length of the input in bytes
     207             :  *
     208             :  * @return The computed CRC16 value (without any XOR applied to it)
     209             :  */
     210           1 : uint16_t crc16_itu_t(uint16_t seed, const uint8_t *src, size_t len);
     211             : 
     212             : /**
     213             :  * @brief Compute the ANSI (or Modbus) variant of CRC-16
     214             :  *
     215             :  * The ANSI variant of CRC-16 uses 0x8005 (0xA001 reflected) as its polynomial
     216             :  * with the initial * value set to 0xffff.
     217             :  *
     218             :  * @param src Input bytes for the computation
     219             :  * @param len Length of the input in bytes
     220             :  *
     221             :  * @return The computed CRC16 value
     222             :  */
     223           1 : static inline uint16_t crc16_ansi(const uint8_t *src, size_t len)
     224             : {
     225             :         return crc16_reflect(0xA001, 0xffff, src, len);
     226             : }
     227             : 
     228             : /**
     229             :  * @brief Generate IEEE conform CRC32 checksum.
     230             :  *
     231             :  * @param  data         Pointer to data on which the CRC should be calculated.
     232             :  * @param  len          Data length.
     233             :  *
     234             :  * @return CRC32 value.
     235             :  *
     236             :  */
     237           1 : uint32_t crc32_ieee(const uint8_t *data, size_t len);
     238             : 
     239             : /**
     240             :  * @brief Update an IEEE conforming CRC32 checksum.
     241             :  *
     242             :  * @param crc   CRC32 checksum that needs to be updated.
     243             :  * @param data  Pointer to data on which the CRC should be calculated.
     244             :  * @param len   Data length.
     245             :  *
     246             :  * @return CRC32 value.
     247             :  *
     248             :  */
     249           1 : uint32_t crc32_ieee_update(uint32_t crc, const uint8_t *data, size_t len);
     250             : 
     251             : /**
     252             :  * @brief Calculate CRC32C (Castagnoli) checksum.
     253             :  *
     254             :  * @param crc       CRC32C checksum that needs to be updated.
     255             :  * @param data      Pointer to data on which the CRC should be calculated.
     256             :  * @param len       Data length.
     257             :  * @param first_pkt Whether this is the first packet in the stream.
     258             :  * @param last_pkt  Whether this is the last packet in the stream.
     259             :  *
     260             :  * @return CRC32 value.
     261             :  *
     262             :  */
     263           1 : uint32_t crc32_c(uint32_t crc, const uint8_t *data,
     264             :                  size_t len, bool first_pkt, bool last_pkt);
     265             : 
     266             : /**
     267             :  * @brief Compute CCITT variant of CRC 8
     268             :  *
     269             :  * Normal CCITT variant of CRC 8 is using 0x07.
     270             :  *
     271             :  * @param initial_value Initial value for the CRC computation
     272             :  * @param buf Input bytes for the computation
     273             :  * @param len Length of the input in bytes
     274             :  *
     275             :  * @return The computed CRC8 value
     276             :  */
     277           1 : uint8_t crc8_ccitt(uint8_t initial_value, const void *buf, size_t len);
     278             : 
     279             : /**
     280             :  * @brief Compute ROHC variant of CRC 8
     281             :  *
     282             :  * ROHC (Robust Header Compression) variant of CRC 8.
     283             :  * Uses 0x07 as the polynomial with reflection.
     284             :  *
     285             :  * @param initial_value Initial value for the CRC computation
     286             :  * @param buf Input bytes for the computation
     287             :  * @param len Length of the input in bytes
     288             :  *
     289             :  * @return The computed CRC8 value
     290             :  */
     291           1 : uint8_t crc8_rohc(uint8_t initial_value, const void *buf, size_t len);
     292             : 
     293             : /**
     294             :  * @brief Compute the CRC-7 checksum of a buffer.
     295             :  *
     296             :  * See JESD84-A441.  Used by the MMC protocol.  Uses 0x09 as the
     297             :  * polynomial with no reflection.  The CRC is left
     298             :  * justified, so bit 7 of the result is bit 6 of the CRC.
     299             :  *
     300             :  * @param seed Value to seed the CRC with
     301             :  * @param src Input bytes for the computation
     302             :  * @param len Length of the input in bytes
     303             :  *
     304             :  * @return The computed CRC7 value
     305             :  */
     306           1 : uint8_t crc7_be(uint8_t seed, const uint8_t *src, size_t len);
     307             : 
     308             : /**
     309             :  * @brief Compute the CRC-4 checksum of a buffer.
     310             :  *
     311             :  * Used by the TMAG5170 sensor. Uses 0x03 as the
     312             :  * polynomial with no reflection. 4 most significant
     313             :  * bits of the CRC result will be set to zero.
     314             :  *
     315             :  * @param seed Value to seed the CRC with
     316             :  * @param src Input bytes for the computation
     317             :  * @param len Length of the input in bytes
     318             :  *
     319             :  * @return The computed CRC4 value
     320             :  */
     321           1 : uint8_t crc4_ti(uint8_t seed, const uint8_t *src, size_t len);
     322             : 
     323             : /**
     324             :  * @brief Generic function for computing CRC 4
     325             :  *
     326             :  * Compute CRC 4 by passing in the address of the input, the input length
     327             :  * and polynomial used in addition to the initial value. The input buffer
     328             :  * must be aligned to a whole byte. It is guaranteed that 4 most significant
     329             :  * bits of the result will be set to zero.
     330             :  *
     331             :  * @param src Input bytes for the computation
     332             :  * @param len Length of the input in bytes
     333             :  * @param polynomial The polynomial to use omitting the leading x^4
     334             :  *        coefficient
     335             :  * @param initial_value Initial value for the CRC computation
     336             :  * @param reversed Should we use reflected/reversed values or not
     337             :  *
     338             :  * @return The computed CRC4 value
     339             :  */
     340           1 : uint8_t crc4(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
     341             :              bool reversed);
     342             : 
     343             : /**
     344             :  * @brief Generate an OpenPGP CRC-24 checksum as defined in RFC 4880 section 6.1.
     345             :  *
     346             :  * @param data A pointer to the data on which the CRC will be calculated.
     347             :  * @param len Data length in bytes.
     348             :  *
     349             :  * @return The CRC-24 value.
     350             :  */
     351           1 : uint32_t crc24_pgp(const uint8_t *data, size_t len);
     352             : 
     353             : /**
     354             :  * @brief Update an OpenPGP CRC-24 checksum.
     355             :  *
     356             :  * @param crc The CRC-24 checksum that needs to be updated. The full 32-bit value of the CRC needs
     357             :  *            to be used between calls, do not mask the value to keep only the last 24 bits.
     358             :  * @param data A pointer to the data on which the CRC will be calculated.
     359             :  * @param len  Data length in bytes.
     360             :  *
     361             :  * @return The CRC-24 value. When the last buffer of data has been processed, mask the value
     362             :  *         with CRC24_FINAL_VALUE_MASK to keep only the meaningful 24 bits of the CRC result.
     363             :  */
     364           1 : uint32_t crc24_pgp_update(uint32_t crc, const uint8_t *data, size_t len);
     365             : 
     366             : /**
     367             :  * @brief Compute a CRC checksum, in a generic way.
     368             :  *
     369             :  * This is a dispatch function that calls the individual CRC routine
     370             :  * determined by @p type.
     371             :  *
     372             :  * For 7, 8, 16 and 24-bit CRCs, the relevant @p seed and @p poly values should
     373             :  * be passed in via the least-significant byte(s).
     374             :  *
     375             :  * Similarly, for 7, 8, 16 and 24-bit CRCs, the relevant result is stored in the
     376             :  * least-significant byte(s) of the returned value.
     377             :  *
     378             :  * @param type CRC algorithm to use.
     379             :  * @param src Input bytes for the computation
     380             :  * @param len Length of the input in bytes
     381             :  * @param seed Value to seed the CRC with
     382             :  * @param poly The polynomial to use omitting the leading coefficient
     383             :  * @param reflect Should we use reflected/reversed values or not
     384             :  * @param first Whether this is the first packet in the stream.
     385             :  * @param last Whether this is the last packet in the stream.
     386             :  * @return uint32_t the computed CRC value
     387             :  */
     388           1 : static inline uint32_t crc_by_type(enum crc_type type, const uint8_t *src, size_t len,
     389             :                                    uint32_t seed, uint32_t poly, bool reflect, bool first,
     390             :                                    bool last)
     391             : {
     392             :         switch (type) {
     393             :         case CRC4:
     394             :                 return crc4(src, len, poly, seed, reflect);
     395             :         case CRC4_TI:
     396             :                 return crc4_ti(seed, src, len);
     397             :         case CRC7_BE:
     398             :                 return crc7_be(seed, src, len);
     399             :         case CRC8:
     400             :                 return crc8(src, len, poly, seed, reflect);
     401             :         case CRC8_CCITT:
     402             :                 return crc8_ccitt(seed, src, len);
     403             :         case CRC8_ROHC:
     404             :                 return crc8_rohc(seed, src, len);
     405             :         case CRC16:
     406             :                 if (reflect) {
     407             :                         return crc16_reflect(poly, seed, src, len);
     408             :                 } else {
     409             :                         return crc16(poly, seed, src, len);
     410             :                 }
     411             :         case CRC16_ANSI:
     412             :                 return crc16_ansi(src, len);
     413             :         case CRC16_CCITT:
     414             :                 return crc16_ccitt(seed, src, len);
     415             :         case CRC16_ITU_T:
     416             :                 return crc16_itu_t(seed, src, len);
     417             :         case CRC24_PGP: {
     418             :                 uint32_t crc = crc24_pgp_update(seed, src, len);
     419             : 
     420             :                 if (last)
     421             :                         crc &= CRC24_FINAL_VALUE_MASK;
     422             :                 return crc;
     423             :         }
     424             :         case CRC32_C:
     425             :                 return crc32_c(seed, src, len, first, last);
     426             :         case CRC32_IEEE:
     427             :                 return crc32_ieee_update(seed, src, len);
     428             :         default:
     429             :                 break;
     430             :         }
     431             : 
     432             :         __ASSERT_NO_MSG(false);
     433             :         return -1;
     434             : }
     435             : 
     436             : /**
     437             :  * @}
     438             :  */
     439             : 
     440             : #ifdef __cplusplus
     441             : }
     442             : #endif
     443             : 
     444             : #endif

Generated by: LCOV version 1.14