Annotation of libelwix/src/crc.c, revision 1.1

1.1     ! misho       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.6 2012/07/22 21:46:23 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, 2012, 2013
        !            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: /* Adler module */
        !            50: const u_int crc_modAdler = 0xFFF1L;
        !            51: 
        !            52: /* All known library CRC types ... */
        !            53: const crcPoly_t crc_Poly[] = {
        !            54:        { 1, (u_int) 0x1, "CRC-1-Parity" }, 
        !            55:        { 4, (u_int) 0x3, "CRC-4-ITU" }, 
        !            56:        { 5, (u_int) 0x15, "CRC-5-ITU" }, 
        !            57:        { 6, (u_int) 0x3, "CRC-6-ITU" }, 
        !            58:        { 7, (u_int) 0x9, "CRC-7-MMC" }, 
        !            59:        { 8, (u_int) 0x8D, "CRC-8-CCITT" }, 
        !            60:        { 10, (u_int) 0x233, "CRC-10" }, 
        !            61:        { 11, (u_int) 0x385, "CRC-11-FlexRay" }, 
        !            62:        { 12, (u_int) 0x80F, "CRC-12-Telco" }, 
        !            63:        { 15, (u_int) 0x4599, "CRC-15-CAN" }, 
        !            64:        { 16, (u_int) 0x8005, "CRC-16-IBM" }, 
        !            65:        { 24, (u_int) 0x864CFB, "CRC-24-Radix64" }, 
        !            66:        { 30, (u_int) 0x2030B9C7, "CRC-30-CDMA" }, 
        !            67:        { 32, (u_int) 0x04C11DB7, "CRC-32-802.3" }
        !            68: };
        !            69: 
        !            70: 
        !            71: /*
        !            72:  * crcReflect() - Reflect all bits of number 
        !            73:  *
        !            74:  * @crcNum = Number for reflection
        !            75:  * @crcBits = Number width bits 
        !            76:  * return: -1 error, !=-1 reflecting number
        !            77:  */
        !            78: inline u_int
        !            79: crcReflect(u_int crcNum, u_char crcBits)
        !            80: {
        !            81:        register u_int i, j, rev;
        !            82: 
        !            83:        for (i = (u_int) 1 << (crcBits - 1), j = 1, rev ^= rev; i; i >>= 1, j <<= 1)
        !            84:                if (crcNum & i)
        !            85:                        rev |= j;
        !            86:        return rev;
        !            87: }
        !            88: 
        !            89: /*
        !            90:  * crcCalc() - Generic CRC calculation function for many sub variants of CRC algorithms
        !            91:  *
        !            92:  * @psBuf = Data for calculation
        !            93:  * @bufLen = Length of data
        !            94:  * @crcBits = CRC algorithm bits (1, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 24, 30, 32)
        !            95:  * @RevOpts = Options for computation (REVOPTS_REVERTBYTE, REVOPTS_REVERTCRC)
        !            96:  * @initCRC = Initial CRC value
        !            97:  * @xorCRC = Last xor CRC value
        !            98:  * return: -1 error, !=-1 CRC checksum
        !            99:  */
        !           100: inline u_int
        !           101: crcCalc(u_char * __restrict psBuf, u_int bufLen, u_char crcBits, u_char RevOpts, u_int initCRC, u_int xorCRC)
        !           102: {
        !           103:        const u_int bits = sizeof(int) * 8 - crcBits;
        !           104:        u_int poly, crchibit, crc;
        !           105:        register u_int i, j, b, ch;
        !           106: 
        !           107:        assert(psBuf);
        !           108: 
        !           109:        switch (crcBits) {
        !           110:                case 1:
        !           111:                        poly = crc_Poly[0].poly_num;
        !           112:                        break;
        !           113:                case 4:
        !           114:                        poly = crc_Poly[1].poly_num;
        !           115:                        break;
        !           116:                case 5:
        !           117:                        poly = crc_Poly[2].poly_num;
        !           118:                        break;
        !           119:                case 6:
        !           120:                        poly = crc_Poly[3].poly_num;
        !           121:                        break;
        !           122:                case 7:
        !           123:                        poly = crc_Poly[4].poly_num;
        !           124:                        break;
        !           125:                case 8:
        !           126:                        poly = crc_Poly[5].poly_num;
        !           127:                        break;
        !           128:                case 10:
        !           129:                        poly = crc_Poly[6].poly_num;
        !           130:                        break;
        !           131:                case 11:
        !           132:                        poly = crc_Poly[7].poly_num;
        !           133:                        break;
        !           134:                case 12:
        !           135:                        poly = crc_Poly[8].poly_num;
        !           136:                        break;
        !           137:                case 15:
        !           138:                        poly = crc_Poly[9].poly_num;
        !           139:                        break;
        !           140:                case 16:
        !           141:                        poly = crc_Poly[10].poly_num;
        !           142:                        break;
        !           143:                case 24:
        !           144:                        poly = crc_Poly[11].poly_num;
        !           145:                        break;
        !           146:                case 30:
        !           147:                        poly = crc_Poly[12].poly_num;
        !           148:                        break;
        !           149:                case 32:
        !           150:                        poly = crc_Poly[13].poly_num;
        !           151:                        break;
        !           152:                default:
        !           153:                        elwix_SetErr(EINVAL, "crcCalc(): Unsupported CRC method!!!");
        !           154:                        return -1;
        !           155:        }
        !           156:        poly <<= bits;
        !           157: 
        !           158:        crchibit = (u_int) 1 << (crcBits - 1);
        !           159:        crchibit <<= bits;
        !           160:        crc = initCRC << bits;
        !           161: 
        !           162:        for (i = 0; i < bufLen; i++) {
        !           163:                ch = (u_int) *psBuf++;
        !           164:                if (RevOpts & REVOPTS_REVERTBYTE)
        !           165:                        ch = crcReflect(ch, 8);
        !           166: 
        !           167:                for (j = 0x80; j; j >>= 1) {
        !           168:                        b = crc & crchibit;
        !           169:                        crc <<= 1;
        !           170: 
        !           171:                        if (ch & j)
        !           172:                                b ^= crchibit;
        !           173:                        if (b)
        !           174:                                crc ^= poly;
        !           175:                }
        !           176:        }
        !           177: 
        !           178:        if (RevOpts & REVOPTS_REVERTCRC)
        !           179:                crc = crcReflect(crc, sizeof(int) * 8);
        !           180:        crc ^= xorCRC << bits;
        !           181:        crc &= (((crchibit - 1) << 1) | 1);
        !           182:        if (!(RevOpts & REVOPTS_REVERTCRC))
        !           183:                crc >>= bits;
        !           184: 
        !           185:        return crc;
        !           186: }
        !           187: 
        !           188: 
        !           189: /*
        !           190:  * crcIP() - Checksum in IP communication
        !           191:  *
        !           192:  * @buf = Data for calculation
        !           193:  * @bufLen = Length of data
        !           194:  * return: -1 error, !=-1 Checksum
        !           195:  */
        !           196: inline u_short
        !           197: crcIP(u_char * __restrict buf, int bufLen)
        !           198: {
        !           199:        register u_int sum;
        !           200:        u_short last = 0, *nBuf = (u_short*) buf;
        !           201: 
        !           202:        assert(buf);
        !           203: 
        !           204:        for (sum = 0; bufLen && bufLen > 1; bufLen -= 2)
        !           205:                sum += *nBuf++;
        !           206:        if (bufLen == 1) {
        !           207:                *(u_char*)(&last) += *(u_char*) nBuf;
        !           208:                sum += last;
        !           209:        }
        !           210: 
        !           211:        sum = (sum >> 16) + (sum & 0xFFFF);
        !           212:        sum += sum >> 16;
        !           213: 
        !           214:        return (u_short) ~sum;
        !           215: }
        !           216: 
        !           217: /*
        !           218:  * crcFletcher16() - Fletcher-16 Checksum computing
        !           219:  *
        !           220:  * @nBuf = Data for calculation
        !           221:  * @bufLen = Length of data
        !           222:  * return: -1 error, !=-1 Checksum
        !           223:  */
        !           224: inline u_short
        !           225: crcFletcher16(u_short * __restrict nBuf, int bufLen)
        !           226: {
        !           227:        register u_short s1, s2;
        !           228:        register u_int clen;
        !           229: 
        !           230:        assert(nBuf);
        !           231: 
        !           232:        s1 = s2 = 0xFF;
        !           233:        while (bufLen) {
        !           234:                clen = bufLen > MAX_FLETCHER16_DIGEST ? MAX_FLETCHER16_DIGEST : bufLen;
        !           235:                bufLen -= clen;
        !           236: 
        !           237:                do {
        !           238:                        s1 += (u_short) *nBuf++;
        !           239:                        s2 += s1;
        !           240:                } while (--clen);
        !           241: 
        !           242:                s1 = (s1 >> 8) + (s1 & 0xFF);
        !           243:                s2 = (s2 >> 8) + (s2 & 0xFF);
        !           244:        }
        !           245: 
        !           246:        return (s2 << 8) | s1;
        !           247: }
        !           248: 
        !           249: /*
        !           250:  * crcFletcher() - Fletcher-32 Checksum computing
        !           251:  *
        !           252:  * @nBuf = Data for calculation
        !           253:  * @bufLen = Length of data
        !           254:  * return: -1 error, !=-1 Checksum
        !           255:  */
        !           256: inline u_int
        !           257: crcFletcher(u_short * __restrict nBuf, int bufLen)
        !           258: {
        !           259:        register u_int s1, s2, clen;
        !           260: 
        !           261:        assert(nBuf);
        !           262: 
        !           263:        s1 = s2 = 0xFFFF;
        !           264:        while (bufLen) {
        !           265:                clen = bufLen > MAX_FLETCHER_DIGEST ? MAX_FLETCHER_DIGEST : bufLen;
        !           266:                bufLen -= clen;
        !           267: 
        !           268:                do {
        !           269:                        s1 += (u_int) *nBuf++;
        !           270:                        s2 += s1;
        !           271:                } while (--clen);
        !           272: 
        !           273:                s1 = (s1 >> 16) + (s1 & 0xFFFF);
        !           274:                s2 = (s2 >> 16) + (s2 & 0xFFFF);
        !           275:        }
        !           276: 
        !           277:        return (s2 << 16) | s1;
        !           278: }
        !           279: 
        !           280: /*
        !           281:  * crcAdler() - crcAdler-32 Checksum computing
        !           282:  *
        !           283:  * @psBuf = Data for calculation
        !           284:  * @bufLen = Length of data
        !           285:  * return: -1 error, !=-1 Checksum
        !           286:  */
        !           287: inline u_int
        !           288: crcAdler(u_char * __restrict psBuf, int bufLen)
        !           289: {
        !           290:        register u_int s1, s2, clen;
        !           291: 
        !           292:        assert(psBuf);
        !           293: 
        !           294:        s1 = 1L;
        !           295:        s2 ^= s2;
        !           296:        while (bufLen) {
        !           297:                clen = bufLen > MAX_ADLER_DIGEST ? MAX_ADLER_DIGEST : bufLen;
        !           298:                bufLen -= clen;
        !           299: 
        !           300:                do {
        !           301:                        s1 += (u_int) *psBuf++;
        !           302:                        s2 += s1;
        !           303:                } while (--clen);
        !           304: 
        !           305:                s1 %= crc_modAdler;
        !           306:                s2 %= crc_modAdler;
        !           307:        }
        !           308: 
        !           309:        return (s2 << 16) | s1;
        !           310: }

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