/************************************************************************* * (C) 2008 AITNET ltd - Sofia/Bulgaria - * by Michael Pounov * * $Author: misho $ * $Id: aitcrc.c,v 1.1 2008/11/05 17:02:55 misho Exp $ * *************************************************************************/ #include "global.h" static int crc_Errno; static char crc_Error[MAX_STR + 1]; const u_long crc_modAdler = 0xFFF1L; const crcPoly_t crc_Poly[] = { { 1, (u_long) 0x1, "CRC-1-Parity" }, { 4, (u_long) 0x3, "CRC-4-ITU" }, { 5, (u_long) 0x15, "CRC-5-ITU" }, { 6, (u_long) 0x3, "CRC-6-ITU" }, { 7, (u_long) 0x9, "CRC-7-MMC" }, { 8, (u_long) 0x8D, "CRC-8-CCITT" }, { 10, (u_long) 0x233, "CRC-10" }, { 11, (u_long) 0x385, "CRC-11-FlexRay" }, { 12, (u_long) 0x80F, "CRC-12-Telco" }, { 15, (u_long) 0x4599, "CRC-15-CAN" }, { 16, (u_long) 0x8005, "CRC-16-IBM" }, { 24, (u_long) 0x864CFB, "CRC-24-Radix64" }, { 30, (u_long) 0x2030B9C7, "CRC-30-CDMA" }, { 32, (u_long) 0x04C11DB7, "CRC-32-802.3" } }; // ---------------------------------------------------------- inline int crc_GetErrno() { return crc_Errno; } inline const char *crc_GetError() { return crc_Error; } // ---------------------------------------------------------- inline u_long crcReflect(u_long crcNum, u_char crcBits) { register u_long i, j, rev; for (i = (u_long) 1 << (crcBits - 1), j = 1, rev ^= rev; i; i >>= 1, j <<= 1) if (crcNum & i) rev |= j; crc_Errno ^= crc_Errno; return rev; } inline u_long crcCalc(u_char * __restrict psBuf, u_int bufLen, u_char crcBits, u_char RevOpts, u_long initCRC, u_long xorCRC) { const u_long bits = sizeof(long) * 8 - crcBits; u_long poly, crchibit, crc; register u_long i, j, b, ch; if (!psBuf) { crc_Errno = 1; strlcpy(crc_Error, "crcCalc(): Invalid parameters!", MAX_STR + 1); return -1; } switch (crcBits) { case 1: poly = crc_Poly[0].poly_num; break; case 4: poly = crc_Poly[1].poly_num; break; case 5: poly = crc_Poly[2].poly_num; break; case 6: poly = crc_Poly[3].poly_num; break; case 7: poly = crc_Poly[4].poly_num; break; case 8: poly = crc_Poly[5].poly_num; break; case 10: poly = crc_Poly[6].poly_num; break; case 11: poly = crc_Poly[7].poly_num; break; case 12: poly = crc_Poly[8].poly_num; break; case 15: poly = crc_Poly[9].poly_num; break; case 16: poly = crc_Poly[10].poly_num; break; case 24: poly = crc_Poly[11].poly_num; break; case 30: poly = crc_Poly[12].poly_num; break; case 32: poly = crc_Poly[13].poly_num; break; default: crc_Errno = 2; strlcpy(crc_Error, "crcCalc(): Unsupported CRC method!!!", MAX_STR + 1); return -1; } poly <<= bits; crchibit = (u_long) 1 << (crcBits - 1); crchibit <<= bits; crc = initCRC << bits; for (i = 0; i < bufLen; i++) { ch = (u_long) *psBuf++; if (RevOpts & REVOPTS_REVERTBYTE) ch = crcReflect(ch, 8); for (j = 0x80; j; j >>= 1) { b = crc & crchibit; crc <<= 1; if (ch & j) b ^= crchibit; if (b) crc ^= poly; } } if (RevOpts & REVOPTS_REVERTCRC) crc = crcReflect(crc, sizeof(long) * 8); crc ^= xorCRC << bits; crc &= (((crchibit - 1) << 1) | 1); if (!(RevOpts & REVOPTS_REVERTCRC)) crc >>= bits; crc_Errno ^= crc_Errno; return crc; } // ---------------------------------------------------------- inline u_short crcIP(u_short * __restrict nBuf, int bufLen) { register u_long sum; if (!nBuf) { crc_Errno = 1; strlcpy(crc_Error, "crcIP(): Invalid parameters!", MAX_STR + 1); return -1; } for (sum = 0; bufLen; bufLen--) sum += *nBuf++; sum = (sum >> 16) + (sum & 0xFFFF); sum += sum >> 16; crc_Errno ^= crc_Errno; return (u_short) ~sum; } inline u_long crcFletcher(u_short * __restrict nBuf, int bufLen) { register u_long s1, s2, clen; if (!nBuf) { crc_Errno = 1; strlcpy(crc_Error, "crcFletcher(): Invalid parameters!", MAX_STR + 1); return -1; } s1 = s2 = 0xFFFF; while (bufLen) { clen = bufLen > MAX_FLETCHER_DIGEST ? MAX_FLETCHER_DIGEST : bufLen; bufLen -= clen; do { s1 += (u_long) *nBuf++; s2 += s1; } while (--clen); s1 = (s1 >> 16) + (s1 & 0xFFFF); s2 = (s2 >> 16) + (s2 & 0xFFFF); } crc_Errno ^= crc_Errno; return (s2 << 16) | s1; } inline u_long crcAdler(u_char * __restrict psBuf, int bufLen) { register u_long s1, s2, clen; if (!psBuf) { crc_Errno = 1; strlcpy(crc_Error, "crcAdler(): Invalid parameters!", MAX_STR + 1); return -1; } s1 = 1L; s2 ^= s2; while (bufLen) { clen = bufLen > MAX_ADLER_DIGEST ? MAX_ADLER_DIGEST : bufLen; bufLen -= clen; do { s1 += (u_long) *psBuf++; s2 += s1; } while (--clen); s1 %= crc_modAdler; s2 %= crc_modAdler; } crc_Errno ^= crc_Errno; return (s2 << 16) | s1; }