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