File:  [ELWIX - Embedded LightWeight unIX -] / libaitcrc / src / aitcrc.c
Revision 1.4.2.2: download - view: text, annotated - select for diffs - revision graph
Wed Sep 14 14:33:56 2011 UTC (12 years, 9 months ago) by misho
Branches: crc2_1
Diff to: branchpoint 1.4: preferred, unified
change crcIP parameters for easy manipulation with byte buffers

    1: /*************************************************************************
    2: * (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
    3: *  by Michael Pounov <misho@openbsd-bg.org>
    4: *
    5: * $Author: misho $
    6: * $Id: aitcrc.c,v 1.4.2.2 2011/09/14 14:33:56 misho Exp $
    7: *
    8: **************************************************************************
    9: The ELWIX and AITNET software is distributed under the following
   10: terms:
   11: 
   12: All of the documentation and software included in the ELWIX and AITNET
   13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   14: 
   15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
   16: 	by Michael Pounov <misho@elwix.org>.  All rights reserved.
   17: 
   18: Redistribution and use in source and binary forms, with or without
   19: modification, are permitted provided that the following conditions
   20: are met:
   21: 1. Redistributions of source code must retain the above copyright
   22:    notice, this list of conditions and the following disclaimer.
   23: 2. Redistributions in binary form must reproduce the above copyright
   24:    notice, this list of conditions and the following disclaimer in the
   25:    documentation and/or other materials provided with the distribution.
   26: 3. All advertising materials mentioning features or use of this software
   27:    must display the following acknowledgement:
   28: This product includes software developed by Michael Pounov <misho@elwix.org>
   29: ELWIX - Embedded LightWeight unIX and its contributors.
   30: 4. Neither the name of AITNET nor the names of its contributors
   31:    may be used to endorse or promote products derived from this software
   32:    without specific prior written permission.
   33: 
   34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
   35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44: SUCH DAMAGE.
   45: */
   46: #include "global.h"
   47: 
   48: 
   49: static int crc_Errno;
   50: static char crc_Error[MAX_STR + 1];
   51: 
   52: // Adler module
   53: const u_int crc_modAdler = 0xFFF1L;
   54: 
   55: // All known library CRC types ...
   56: const crcPoly_t crc_Poly[] = {
   57: 	{ 1, (u_int) 0x1, "CRC-1-Parity" }, 
   58: 	{ 4, (u_int) 0x3, "CRC-4-ITU" }, 
   59: 	{ 5, (u_int) 0x15, "CRC-5-ITU" }, 
   60: 	{ 6, (u_int) 0x3, "CRC-6-ITU" }, 
   61: 	{ 7, (u_int) 0x9, "CRC-7-MMC" }, 
   62: 	{ 8, (u_int) 0x8D, "CRC-8-CCITT" }, 
   63: 	{ 10, (u_int) 0x233, "CRC-10" }, 
   64: 	{ 11, (u_int) 0x385, "CRC-11-FlexRay" }, 
   65: 	{ 12, (u_int) 0x80F, "CRC-12-Telco" }, 
   66: 	{ 15, (u_int) 0x4599, "CRC-15-CAN" }, 
   67: 	{ 16, (u_int) 0x8005, "CRC-16-IBM" }, 
   68: 	{ 24, (u_int) 0x864CFB, "CRC-24-Radix64" }, 
   69: 	{ 30, (u_int) 0x2030B9C7, "CRC-30-CDMA" }, 
   70: 	{ 32, (u_int) 0x04C11DB7, "CRC-32-802.3" }
   71: };
   72: 
   73: // ----------------------------------------------------------
   74: 
   75: //
   76: // Error maintenance functions ...
   77: //
   78: 
   79: // crc_GetErrno() Get error code of last operation
   80: inline int
   81: crc_GetErrno()
   82: {
   83: 	return crc_Errno;
   84: }
   85: 
   86: // crc_GetError() Get error text of last operation
   87: inline const char *
   88: crc_GetError()
   89: {
   90: 	return crc_Error;
   91: }
   92: 
   93: // crcSetErr() Set error to variables for internal use!!!
   94: inline void
   95: crcSetErr(int eno, char *estr, ...)
   96: {
   97: 	va_list lst;
   98: 
   99: 	crc_Errno = eno;
  100: 	memset(crc_Error, 0, MAX_STR + 1);
  101: 	va_start(lst, estr);
  102: 	vsnprintf(crc_Error, MAX_STR + 1, estr, lst);
  103: 	va_end(lst);
  104: }
  105: 
  106: // ----------------------------------------------------------
  107: 
  108: /*
  109:  * crcReflect() Reflect all bits of number 
  110:  * @crcNum = Number for reflection
  111:  * @crcBits = Number width bits 
  112:  * return: -1 error, !=-1 reflecting number
  113:  */
  114: inline u_int
  115: crcReflect(u_int crcNum, u_char crcBits)
  116: {
  117: 	register u_int i, j, rev;
  118: 
  119: 	for (i = (u_int) 1 << (crcBits - 1), j = 1, rev ^= rev; i; i >>= 1, j <<= 1)
  120: 		if (crcNum & i)
  121: 			rev |= j;
  122: 
  123: 	crc_Errno ^= crc_Errno;
  124: 	return rev;
  125: }
  126: 
  127: /*
  128:  * crcCalc() Generic CRC calculation function for many sub variants of CRC algorithms
  129:  * @psBuf = Data for calculation
  130:  * @bufLen = Length of data
  131:  * @crcBits = CRC algorithm bits (1, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 24, 30, 32)
  132:  * @RevOpts = Options for computation (REVOPTS_REVERTBYTE, REVOPTS_REVERTCRC)
  133:  * @initCRC = Initial CRC value
  134:  * @xorCRC = Last xor CRC value
  135:  * return: -1 error, !=-1 CRC checksum
  136:  */
  137: inline u_int
  138: crcCalc(u_char * __restrict psBuf, u_int bufLen, u_char crcBits, u_char RevOpts, u_int initCRC, u_int xorCRC)
  139: {
  140: 	const u_int bits = sizeof(int) * 8 - crcBits;
  141: 	u_int poly, crchibit, crc;
  142: 	register u_int i, j, b, ch;
  143: 
  144: 	if (!psBuf) {
  145: 		crc_Errno = 1;
  146: 		strlcpy(crc_Error, "crcCalc(): Invalid parameters!", MAX_STR + 1);
  147: 		return -1;
  148: 	}
  149: 
  150: 	switch (crcBits) {
  151: 		case 1:
  152: 			poly = crc_Poly[0].poly_num;
  153: 			break;
  154: 		case 4:
  155: 			poly = crc_Poly[1].poly_num;
  156: 			break;
  157: 		case 5:
  158: 			poly = crc_Poly[2].poly_num;
  159: 			break;
  160: 		case 6:
  161: 			poly = crc_Poly[3].poly_num;
  162: 			break;
  163: 		case 7:
  164: 			poly = crc_Poly[4].poly_num;
  165: 			break;
  166: 		case 8:
  167: 			poly = crc_Poly[5].poly_num;
  168: 			break;
  169: 		case 10:
  170: 			poly = crc_Poly[6].poly_num;
  171: 			break;
  172: 		case 11:
  173: 			poly = crc_Poly[7].poly_num;
  174: 			break;
  175: 		case 12:
  176: 			poly = crc_Poly[8].poly_num;
  177: 			break;
  178: 		case 15:
  179: 			poly = crc_Poly[9].poly_num;
  180: 			break;
  181: 		case 16:
  182: 			poly = crc_Poly[10].poly_num;
  183: 			break;
  184: 		case 24:
  185: 			poly = crc_Poly[11].poly_num;
  186: 			break;
  187: 		case 30:
  188: 			poly = crc_Poly[12].poly_num;
  189: 			break;
  190: 		case 32:
  191: 			poly = crc_Poly[13].poly_num;
  192: 			break;
  193: 		default:
  194: 			crc_Errno = 2;
  195: 			strlcpy(crc_Error, "crcCalc(): Unsupported CRC method!!!", MAX_STR + 1);
  196: 			return -1;
  197: 	}
  198: 	poly <<= bits;
  199: 
  200: 	crchibit = (u_int) 1 << (crcBits - 1);
  201: 	crchibit <<= bits;
  202: 	crc = initCRC << bits;
  203: 
  204: 	for (i = 0; i < bufLen; i++) {
  205: 		ch = (u_int) *psBuf++;
  206: 		if (RevOpts & REVOPTS_REVERTBYTE)
  207: 			ch = crcReflect(ch, 8);
  208: 
  209: 		for (j = 0x80; j; j >>= 1) {
  210: 			b = crc & crchibit;
  211: 			crc <<= 1;
  212: 
  213: 			if (ch & j)
  214: 				b ^= crchibit;
  215: 			if (b)
  216: 				crc ^= poly;
  217: 		}
  218: 	}
  219: 
  220: 	if (RevOpts & REVOPTS_REVERTCRC)
  221: 		crc = crcReflect(crc, sizeof(int) * 8);
  222: 	crc ^= xorCRC << bits;
  223: 	crc &= (((crchibit - 1) << 1) | 1);
  224: 	if (!(RevOpts & REVOPTS_REVERTCRC))
  225: 		crc >>= bits;
  226: 
  227: 	crc_Errno ^= crc_Errno;
  228: 	return crc;
  229: }
  230: 
  231: // ----------------------------------------------------------
  232: 
  233: /*
  234:  * crcIP() Checksum in IP communication
  235:  * @buf = Data for calculation
  236:  * @bufLen = Length of data
  237:  * return: -1 error, !=-1 Checksum
  238:  */
  239: inline u_short
  240: crcIP(u_char * __restrict buf, int bufLen)
  241: {
  242: 	register u_int sum;
  243: 	u_short last = 0, *nBuf = (u_short*) buf;
  244: 
  245: 	if (!buf) {
  246: 		crc_Errno = 1;
  247: 		strlcpy(crc_Error, "crcIP(): Invalid parameters!", MAX_STR + 1);
  248: 		return -1;
  249: 	}
  250: 
  251: 	for (sum = 0; bufLen && bufLen > 1; bufLen -= 2)
  252: 		sum += *nBuf++;
  253: 	if (bufLen == 1) {
  254: 		*(u_char*)(&last) += *(u_char*) nBuf;
  255: 		sum += last;
  256: 	}
  257: 
  258: 	sum = (sum >> 16) + (sum & 0xFFFF);
  259: 	sum += sum >> 16;
  260: 
  261: 	crc_Errno ^= crc_Errno;
  262: 	return (u_short) ~sum;
  263: }
  264: 
  265: /*
  266:  * crcFletcher16() Fletcher-16 Checksum computing
  267:  * @nBuf = Data for calculation
  268:  * @bufLen = Length of data
  269:  * return: -1 error, !=-1 Checksum
  270:  */
  271: inline u_short
  272: crcFletcher16(u_short * __restrict nBuf, int bufLen)
  273: {
  274: 	register u_short s1, s2;
  275: 	register u_int clen;
  276: 
  277: 	if (!nBuf) {
  278: 		crc_Errno = 1;
  279: 		strlcpy(crc_Error, "crcFletcher16(): Invalid parameters!", MAX_STR + 1);
  280: 		return -1;
  281: 	}
  282: 
  283: 	s1 = s2 = 0xFF;
  284: 	while (bufLen) {
  285: 		clen = bufLen > MAX_FLETCHER16_DIGEST ? MAX_FLETCHER16_DIGEST : bufLen;
  286: 		bufLen -= clen;
  287: 
  288: 		do {
  289: 			s1 += (u_short) *nBuf++;
  290: 			s2 += s1;
  291: 		} while (--clen);
  292: 
  293: 		s1 = (s1 >> 8) + (s1 & 0xFF);
  294: 		s2 = (s2 >> 8) + (s2 & 0xFF);
  295: 	}
  296: 
  297: 	crc_Errno ^= crc_Errno;
  298: 	return (s2 << 8) | s1;
  299: }
  300: 
  301: /*
  302:  * crcFletcher() Fletcher-32 Checksum computing
  303:  * @nBuf = Data for calculation
  304:  * @bufLen = Length of data
  305:  * return: -1 error, !=-1 Checksum
  306:  */
  307: inline u_int
  308: crcFletcher(u_short * __restrict nBuf, int bufLen)
  309: {
  310: 	register u_int s1, s2, clen;
  311: 
  312: 	if (!nBuf) {
  313: 		crc_Errno = 1;
  314: 		strlcpy(crc_Error, "crcFletcher(): Invalid parameters!", MAX_STR + 1);
  315: 		return -1;
  316: 	}
  317: 
  318: 	s1 = s2 = 0xFFFF;
  319: 	while (bufLen) {
  320: 		clen = bufLen > MAX_FLETCHER_DIGEST ? MAX_FLETCHER_DIGEST : bufLen;
  321: 		bufLen -= clen;
  322: 
  323: 		do {
  324: 			s1 += (u_int) *nBuf++;
  325: 			s2 += s1;
  326: 		} while (--clen);
  327: 
  328: 		s1 = (s1 >> 16) + (s1 & 0xFFFF);
  329: 		s2 = (s2 >> 16) + (s2 & 0xFFFF);
  330: 	}
  331: 
  332: 	crc_Errno ^= crc_Errno;
  333: 	return (s2 << 16) | s1;
  334: }
  335: 
  336: /*
  337:  * crcAdler() crcAdler-32 Checksum computing
  338:  * @psBuf = Data for calculation
  339:  * @bufLen = Length of data
  340:  * return: -1 error, !=-1 Checksum
  341:  */
  342: inline u_int
  343: crcAdler(u_char * __restrict psBuf, int bufLen)
  344: {
  345: 	register u_int s1, s2, clen;
  346: 
  347: 	if (!psBuf) {
  348: 		crc_Errno = 1;
  349: 		strlcpy(crc_Error, "crcAdler(): Invalid parameters!", MAX_STR + 1);
  350: 		return -1;
  351: 	}
  352: 
  353: 	s1 = 1L;
  354: 	s2 ^= s2;
  355: 	while (bufLen) {
  356: 		clen = bufLen > MAX_ADLER_DIGEST ? MAX_ADLER_DIGEST : bufLen;
  357: 		bufLen -= clen;
  358: 
  359: 		do {
  360: 			s1 += (u_int) *psBuf++;
  361: 			s2 += s1;
  362: 		} while (--clen);
  363: 
  364: 		s1 %= crc_modAdler;
  365: 		s2 %= crc_modAdler;
  366: 	}
  367: 
  368: 	crc_Errno ^= crc_Errno;
  369: 	return (s2 << 16) | s1;
  370: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>