I have two sources to calculate the seemingly same crc value. I can not figure out why the 'boost/crc.hpp' implementation differs from the 'linux/lib/crc-ccitt.c' implementation.
Here is an example that illustrates the Problem. It is sligthly longer since i do not have the Linux kernel source on my Computer. It compiles if you link boost to it.
The Problem is that Linux and boost do not agree on the crc value. The Linux source states that:
- The polynomial ... 0x8408.
- Add the implicit x^16, and you have the standard CRC-CCITT.
I do not know how to apply x^16 but i die edit this question to reflect the deviating polynomial.
#include <stdio.h>
#include <boost\crc.hpp>
typedef unsigned short u16;
typedef unsigned char u8;
/*
* linux/lib/crc-ccitt.c
*
* This source code is licensed under the GNU General Public License,
* Version 2. See the file COPYING for more details.
*/
/*modified for minimal example on stackoverflow*/
/*original source from http://mirrors.neusoft.edu.cn/rpi-kernel/lib/crc-ccitt.c */
u16 const crc_ccitt_table[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
//from crc-ccitt.h
static inline u16 crc_ccitt_byte(u16 crc, const u8 c)
{
return (crc >> 8) ^ crc_ccitt_table[(crc ^ c) & 0xff];
}
u16 crc_ccitt(u16 crc, u8 const *buffer, size_t len)
{
while (len--)
crc = crc_ccitt_byte(crc, *buffer++);
return crc;
}
#define check(X, Y) \
if (X != Y) { \
printf("%s != %s\n", #X, #Y); \
} else { \
printf("%s == %s !!! celebrate\n", #X, #Y); \
}
void runTestSet(unsigned char * data, unsigned size)
{
u16 linux = crc_ccitt(0xFFFF, data, size);
boost::crc_ccitt_type boost_crc_ccitt_type;
boost::crc_16_type boost_crc_16_type;
boost::crc_32_type boost_crc_32_type;
boost::crc_xmodem_type boost_crc_xmodem_type;
boost::crc_optimal<16, 0x8408, 0xFFFF, 0, false, false> boost_crc_optimal_16_8408_FFFF_0_0_0;
boost::crc_optimal<16, 0x8408, 0xFFFF, 0, true, true> boost_crc_optimal_16_8408_FFFF_0_1_1;
boost::crc_optimal<16, 0xA001, 0xFFFF, 0, true, true> boost_crc_optimal_16_A001_FFFF_0_1_1;
boost::crc_optimal<16, 0x8408, 0xFFFF, 0, true, false> boost_crc_optimal_16_8408_FFFF_0_1_0;
boost::crc_optimal<16, 0x856F, 0xFFFF, 0, true, true> boost_crc_optimal_16_856F_FFFF_0_1_1;
boost::crc_optimal<16, 0x856F, 0xFFFF, 0, true, false> boost_crc_optimal_16_856F_FFFF_0_1_0;
boost_crc_ccitt_type.process_bytes(data, size);
boost_crc_16_type.process_bytes(data, size);
boost_crc_32_type.process_bytes(data, size);
boost_crc_xmodem_type.process_bytes(data, size);
boost_crc_optimal_16_8408_FFFF_0_0_0.process_bytes(data, size);
boost_crc_optimal_16_8408_FFFF_0_1_1.process_bytes(data, size);
boost_crc_optimal_16_A001_FFFF_0_1_1.process_bytes(data, size);
boost_crc_optimal_16_8408_FFFF_0_1_0.process_bytes(data, size);
boost_crc_optimal_16_856F_FFFF_0_1_1.process_bytes(data, size);
boost_crc_optimal_16_856F_FFFF_0_1_0.process_bytes(data, size);
printf("Testing with sequence: '");
for (unsigned n = 0; n < size; ++n)
{
if (n > 0) printf(" ");
printf("0x%02X", data[n]);
}
printf("'\n");
check(boost_crc_ccitt_type.checksum(), linux);
check(boost_crc_16_type.checksum(), linux);
check(boost_crc_32_type.checksum(), linux);
check(boost_crc_xmodem_type.checksum(), linux);
check(boost_crc_optimal_16_8408_FFFF_0_0_0.checksum(), linux);
check(boost_crc_optimal_16_8408_FFFF_0_1_1.checksum(), linux);
check(boost_crc_optimal_16_A001_FFFF_0_1_1.checksum(), linux);
check(boost_crc_optimal_16_8408_FFFF_0_1_0.checksum(), linux);
check(boost_crc_optimal_16_856F_FFFF_0_1_1.checksum(), linux);
check(boost_crc_optimal_16_856F_FFFF_0_1_0.checksum(), linux);
printf("End Of Testrun\n\n");
}
int main()
{
unsigned char simple[] = {0x80};
unsigned char sequence[] = "123456789";
runTestSet(simple, sizeof(simple));
runTestSet(sequence, sizeof(sequence));
return 0;
}
I see that i did not state my usecase for this. I have a System dependency and need to use the incorrect(?) Linux crc. I want to trim the boost implementation in a way that allows me to do this using boost instead.
The output on my machine is:
Through Trial and error i found a solution that seems to produce the correct hits. Thanks everyone for the hints. This type
boost::crc_optimal<16, 0x1021, 0xFFFF, 0, true, true>
seems to be correct.I do not know why and that worries me a bit.
Given
lib/crc-ccitt.c
does not use the 0x1021 polynomial required for CRC-CCITT. So, i think boost version is correct sincecrc_ccitt_type
is a typedef:P.S. Warning: your line
size = sizeof(data) / sizeof(data[0])
is not correct, but it gives right number. This counts number of elements, not number of bytes (but since sizeof(char)==1 it caclulates right size).update - based on these web site crc calculators
(choose ccitt(0xffff)) http://www.lammertbies.nl/comm/info/crc-calculation.html
(choose crc ccitt) http://www.zorc.breitbandkatze.de/crc.html
A third site that calls this version crc-16-ccitt-false, and also lists the other variations also called ccitt.
http://reveng.sourceforge.net/crc-catalogue/16.htm#crc.cat.crc-16-ccitt-false
In this case the bits are not reversed. Also the 9 byte string "123456789" seems like a common test. However other web sites mention that some versions of ccitt do reverse the bits as done in the linux example. My guess is that which one to use will be protocol / device specific. At least now you have both the reversed (linux) and non-reversed (the code in this answer) if you need to switch.
Example code added:
A CRC is the remainder after doing a Galois type divide of a string of bits by a n bit polynomial, producing an n-1 bit remainder. In the case of a floppy disk, a 17 bit polynomial, 0x11021 is used to produce a 16 bit remainder. The logic for each bit goes something like this:
This can be also implemented s:
Example code. This should match the boost code.
The table from the question does indeed use the polynomial 0x1021. This can be checked by generating the table with this short program: