File:  [ELWIX - Embedded LightWeight unIX -] / libaitcrc / src / aitcrc.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Nov 5 17:02:55 2008 UTC (15 years, 8 months ago) by misho
Branches: misho
CVS tags: start, crc1_1
AITNET library for computing CRC

/*************************************************************************
* (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
*  by Michael Pounov <misho@openbsd-bg.org>
*
* $Author: misho $
* $Id: aitcrc.c,v 1.1.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;
}

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