1 //-----------------------------------------------------------------------------
2 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
3 // at your option, any later version. See the LICENSE.txt file for the text of
5 //-----------------------------------------------------------------------------
7 //-----------------------------------------------------------------------------
11 #include "commonutil.h"
13 static uint16_t crc_table
[256];
14 static bool crc_table_init
= false;
15 static CrcType_t current_crc_type
= CRC_NONE
;
17 void init_table(CrcType_t crctype
) {
19 // same crc algo, and initialised already
20 if (crctype
== current_crc_type
&& crc_table_init
)
23 // not the same crc algo. reset table.
24 if (crctype
!= current_crc_type
)
27 current_crc_type
= crctype
;
35 generate_table(CRC16_POLY_CCITT
, true);
39 generate_table(CRC16_POLY_CCITT
, false);
42 generate_table(CRC16_POLY_LEGIC
, true);
45 generate_table(CRC16_POLY_CCITT
, false);
48 generate_table(CRC16_POLY_CCITT
, true);
51 generate_table(CRC16_POLY_CCITT
, false);
54 crc_table_init
= false;
55 current_crc_type
= CRC_NONE
;
60 void generate_table(uint16_t polynomial
, bool refin
) {
62 for (uint16_t i
= 0; i
< 256; i
++) {
69 for (uint16_t j
= 0; j
< 8; j
++) {
71 if ((crc
^ c
) & 0x8000)
72 crc
= (crc
<< 1) ^ polynomial
;
83 crc_table_init
= true;
86 void reset_table(void) {
87 memset(crc_table
, 0, sizeof(crc_table
));
88 crc_table_init
= false;
89 current_crc_type
= CRC_NONE
;
92 // table lookup LUT solution
93 uint16_t crc16_fast(uint8_t const *d
, size_t n
, uint16_t initval
, bool refin
, bool refout
) {
95 // fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip.
96 // only usable with polynom orders of 8, 16, 24 or 32.
100 uint16_t crc
= initval
;
103 crc
= reflect16(crc
);
106 while (n
--) crc
= (crc
<< 8) ^ crc_table
[((crc
>> 8) ^ *d
++) & 0xFF ];
108 while (n
--) crc
= (crc
>> 8) ^ crc_table
[(crc
& 0xFF) ^ *d
++];
111 crc
= reflect16(crc
);
116 // bit looped solution TODO REMOVED
117 uint16_t update_crc16_ex(uint16_t crc
, uint8_t c
, uint16_t polynomial
) {
119 uint16_t v
= (crc
^ c
) & 0xff;
121 for (uint16_t i
= 0; i
< 8; i
++) {
124 tmp
= (tmp
>> 1) ^ polynomial
;
130 return ((crc
>> 8) ^ tmp
) & 0xffff;
132 uint16_t update_crc16(uint16_t crc
, uint8_t c
) {
133 return update_crc16_ex(crc
, c
, CRC16_POLY_CCITT
);
136 // two ways. msb or lsb loop.
137 uint16_t Crc16(uint8_t const *d
, size_t length
, uint16_t remainder
, uint16_t polynomial
, bool refin
, bool refout
) {
141 for (uint32_t i
= 0; i
< length
; ++i
) {
143 if (refin
) c
= reflect8(c
);
146 remainder
^= (c
<< 8);
149 for (uint8_t j
= 8; j
; --j
) {
150 if (remainder
& 0x8000) {
151 remainder
= (remainder
<< 1) ^ polynomial
;
158 remainder
= reflect16(remainder
);
163 void compute_crc(CrcType_t ct
, const uint8_t *d
, size_t n
, uint8_t *first
, uint8_t *second
) {
165 // can't calc a crc on less than 1 byte
178 crc
= crc16_x25(d
, n
);
181 crc
= crc16_iclass(d
, n
);
185 crc
= crc16_xmodem(d
, n
);
188 crc
= crc16_ccitt(d
, n
);
191 crc
= crc16_kermit(d
, n
);
194 crc
= crc16_fdxb(d
, n
);
202 *first
= (crc
& 0xFF);
203 *second
= ((crc
>> 8) & 0xFF);
205 uint16_t Crc16ex(CrcType_t ct
, const uint8_t *d
, size_t n
) {
207 // can't calc a crc on less than 3 byte. (1byte + 2 crc bytes)
213 return crc16_a(d
, n
);
217 return crc16_x25(d
, n
);
219 return crc16_iclass(d
, n
);
222 return crc16_xmodem(d
, n
);
224 return crc16_ccitt(d
, n
);
226 return crc16_kermit(d
, n
);
228 return crc16_fdxb(d
, n
);
241 // d buffer with data
242 // n length (including crc)
244 // This function uses the message + crc bytes in order to compare the "residue" afterwards.
245 // crc16 algos like CRC-A become 0x0000
246 // while CRC-15693 become 0x0F47
247 // If calculated with crc bytes, the residue should be 0xF0B8
248 bool check_crc(CrcType_t ct
, const uint8_t *d
, size_t n
) {
250 // can't calc a crc on less than 3 byte. (1byte + 2 crc bytes)
251 if (n
< 3) return false;
257 return (crc16_a(d
, n
) == 0);
260 return (crc16_x25(d
, n
) == X25_CRC_CHECK
);
262 return (crc16_x25(d
, n
) == X25_CRC_CHECK
);
264 return (crc16_iclass(d
, n
) == 0);
267 return (crc16_xmodem(d
, n
) == 0);
269 return (crc16_ccitt(d
, n
) == 0);
271 return (crc16_kermit(d
, n
) == 0);
273 return (crc16_fdxb(d
, n
) == 0);
284 // poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 residue=0x0000 name="CRC-16/CCITT-FALSE"
285 uint16_t crc16_ccitt(uint8_t const *d
, size_t n
) {
286 return crc16_fast(d
, n
, 0xffff, false, false);
289 // FDX-B ISO11784/85) uses KERMIT/CCITT
290 // poly 0x xx init=0x000 refin=false refout=true xorout=0x0000 ...
291 uint16_t crc16_fdxb(uint8_t const *d
, size_t n
) {
292 return crc16_fast(d
, n
, 0x0000, false, true);
295 // poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 name="KERMIT"
296 uint16_t crc16_kermit(uint8_t const *d
, size_t n
) {
297 return crc16_fast(d
, n
, 0x0000, true, true);
300 // FeliCa uses XMODEM
301 // poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 name="XMODEM"
302 uint16_t crc16_xmodem(uint8_t const *d
, size_t n
) {
303 return crc16_fast(d
, n
, 0x0000, false, false);
306 // Following standards uses X-25
309 // ISO/IEC 13239 (formerly ISO/IEC 3309)
310 // poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff name="X-25"
311 uint16_t crc16_x25(uint8_t const *d
, size_t n
) {
312 uint16_t crc
= crc16_fast(d
, n
, 0xffff, true, true);
317 // poly=0x1021 init=0xc6c6 refin=true refout=true xorout=0x0000 name="CRC-A"
318 uint16_t crc16_a(uint8_t const *d
, size_t n
) {
319 return crc16_fast(d
, n
, 0xC6C6, true, true);
323 // initvalue 0x4807 reflected 0xE012
324 // poly 0x1021 reflected 0x8408
325 // poly=0x1021 init=0x4807 refin=true refout=true xorout=0x0BC3 check=0xF0B8 name="CRC-16/ICLASS"
326 uint16_t crc16_iclass(uint8_t const *d
, size_t n
) {
327 return crc16_fast(d
, n
, 0x4807, true, true);
330 // This CRC-16 is used in Legic Advant systems.
331 // poly=0xB400, init=depends refin=true refout=true xorout=0x0000 check= name="CRC-16/LEGIC"
332 uint16_t crc16_legic(uint8_t const *d
, size_t n
, uint8_t uidcrc
) {
333 uint16_t initial
= uidcrc
<< 8 | uidcrc
;
334 return crc16_fast(d
, n
, initial
, true, true);