/************************************************************************* * (C) 2008 AITNET ltd - Sofia/Bulgaria - * by Michael Pounov * * $Author: misho $ * $Id: aitcrc.c,v 1.2.2.1 2010/06/13 16:10:16 misho Exp $ * *************************************************************************/ #include "global.h" static int crc_Errno; static char crc_Error[MAX_STR + 1]; // Adler module const u_int crc_modAdler = 0xFFF1L; // All known library CRC types ... const crcPoly_t crc_Poly[] = { { 1, (u_int) 0x1, "CRC-1-Parity" }, { 4, (u_int) 0x3, "CRC-4-ITU" }, { 5, (u_int) 0x15, "CRC-5-ITU" }, { 6, (u_int) 0x3, "CRC-6-ITU" }, { 7, (u_int) 0x9, "CRC-7-MMC" }, { 8, (u_int) 0x8D, "CRC-8-CCITT" }, { 10, (u_int) 0x233, "CRC-10" }, { 11, (u_int) 0x385, "CRC-11-FlexRay" }, { 12, (u_int) 0x80F, "CRC-12-Telco" }, { 15, (u_int) 0x4599, "CRC-15-CAN" }, { 16, (u_int) 0x8005, "CRC-16-IBM" }, { 24, (u_int) 0x864CFB, "CRC-24-Radix64" }, { 30, (u_int) 0x2030B9C7, "CRC-30-CDMA" }, { 32, (u_int) 0x04C11DB7, "CRC-32-802.3" } }; // ---------------------------------------------------------- // // Error maintenance functions ... // // crc_GetErrno() Get error code of last operation inline int crc_GetErrno() { return crc_Errno; } // crc_GetError() Get error text of last operation inline const char *crc_GetError() { return crc_Error; } // crcSetErr() Set error to variables for internal use!!! inline void crcSetErr(int eno, char *estr, ...) { va_list lst; crc_Errno = eno; memset(crc_Error, 0, MAX_STR + 1); va_start(lst, estr); vsnprintf(crc_Error, MAX_STR + 1, estr, lst); va_end(lst); } // ---------------------------------------------------------- /* * crcReflect() Reflect all bits of number * @crcNum = Number for reflection * @crcBits = Number width bits * return: -1 error, !=-1 reflecting number */ inline u_int crcReflect(u_int crcNum, u_char crcBits) { register u_int i, j, rev; for (i = (u_int) 1 << (crcBits - 1), j = 1, rev ^= rev; i; i >>= 1, j <<= 1) if (crcNum & i) rev |= j; crc_Errno ^= crc_Errno; return rev; } /* * crcCalc() Generic CRC calculation function for many sub variants of CRC algorithms * @psBuf = Data for calculation * @bufLen = Length of data * @crcBits = CRC algorithm bits (1, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 24, 30, 32) * @RevOpts = Options for computation (REVOPTS_REVERTBYTE, REVOPTS_REVERTCRC) * @initCRC = Initial CRC value * @xorCRC = Last xor CRC value * return: -1 error, !=-1 CRC checksum */ inline u_int crcCalc(u_char * __restrict psBuf, u_int bufLen, u_char crcBits, u_char RevOpts, u_int initCRC, u_int xorCRC) { const u_int bits = sizeof(int) * 8 - crcBits; u_int poly, crchibit, crc; register u_int 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_int) 1 << (crcBits - 1); crchibit <<= bits; crc = initCRC << bits; for (i = 0; i < bufLen; i++) { ch = (u_int) *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(int) * 8); crc ^= xorCRC << bits; crc &= (((crchibit - 1) << 1) | 1); if (!(RevOpts & REVOPTS_REVERTCRC)) crc >>= bits; crc_Errno ^= crc_Errno; return crc; } // ---------------------------------------------------------- /* * crcIP() Checksum in IP communication * @nBuf = Data for calculation * @bufLen = Length of data * return: -1 error, !=-1 Checksum */ inline u_short crcIP(u_short * __restrict nBuf, int bufLen) { register u_int 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; } /* * crcFletcher16() Fletcher-16 Checksum computing * @nBuf = Data for calculation * @bufLen = Length of data * return: -1 error, !=-1 Checksum */ inline u_short crcFletcher16(u_short * __restrict nBuf, int bufLen) { register u_short s1, s2; register u_int clen; if (!nBuf) { crc_Errno = 1; strlcpy(crc_Error, "crcFletcher16(): Invalid parameters!", MAX_STR + 1); return -1; } s1 = s2 = 0xFF; while (bufLen) { clen = bufLen > MAX_FLETCHER16_DIGEST ? MAX_FLETCHER16_DIGEST : bufLen; bufLen -= clen; do { s1 += (u_short) *nBuf++; s2 += s1; } while (--clen); s1 = (s1 >> 8) + (s1 & 0xFF); s2 = (s2 >> 8) + (s2 & 0xFF); } crc_Errno ^= crc_Errno; return (s2 << 8) | s1; } /* * crcFletcher() Fletcher-32 Checksum computing * @nBuf = Data for calculation * @bufLen = Length of data * return: -1 error, !=-1 Checksum */ inline u_int crcFletcher(u_short * __restrict nBuf, int bufLen) { register u_int 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_int) *nBuf++; s2 += s1; } while (--clen); s1 = (s1 >> 16) + (s1 & 0xFFFF); s2 = (s2 >> 16) + (s2 & 0xFFFF); } crc_Errno ^= crc_Errno; return (s2 << 16) | s1; } /* * crcAdler() crcAdler-32 Checksum computing * @psBuf = Data for calculation * @bufLen = Length of data * return: -1 error, !=-1 Checksum */ inline u_int crcAdler(u_char * __restrict psBuf, int bufLen) { register u_int 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_int) *psBuf++; s2 += s1; } while (--clen); s1 %= crc_modAdler; s2 %= crc_modAdler; } crc_Errno ^= crc_Errno; return (s2 << 16) | s1; }