diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-03-22 19:25:39 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2014-03-22 19:25:39 +0100 |
commit | aaa059ef1988f3e6af722a2a7d79123cfd3b5e2f (patch) | |
tree | 4d6e4b7ba9bfd65574124840037cefcfddf1ecb0 | |
download | etisnoop-aaa059ef1988f3e6af722a2a7d79123cfd3b5e2f.tar.gz etisnoop-aaa059ef1988f3e6af722a2a7d79123cfd3b5e2f.tar.bz2 etisnoop-aaa059ef1988f3e6af722a2a7d79123cfd3b5e2f.zip |
Add etisnoop tool
-rw-r--r-- | Makefile | 10 | ||||
-rw-r--r-- | etisnoop.c | 553 | ||||
-rw-r--r-- | lib_crc.c | 459 | ||||
-rw-r--r-- | lib_crc.h | 66 |
4 files changed, 1088 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..2acfe75 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ + +CC=gcc + +all: etisnoop + +etisnoop: etisnoop.c lib_crc.c lib_crc.h + $(CC) -Wall -ggdb etisnoop.c lib_crc.c -o etisnoop + +clean: + rm -f etisnoop *.o diff --git a/etisnoop.c b/etisnoop.c new file mode 100644 index 0000000..643d3d7 --- /dev/null +++ b/etisnoop.c @@ -0,0 +1,553 @@ +/* + Copyright (C) 2014 CSP Innovazione nelle ICT s.c.a r.l. (http://www.csp.it/) + All rights reserved. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + etisnoop.c + Parse ETI NI G.703 file + + Authors: + Sergio Sagliocco <sergio.sagliocco@csp.it> +*/ + + + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include "lib_crc.h" + + +#define ETINIPACKETSIZE 6144 + + +void printbuf(char* h,int level, unsigned char* b, unsigned short int l, char* d); +void decodeFIG(unsigned char* figdata, unsigned char figlen,unsigned short int figtype, unsigned short int indent); + +int main (int c, char *v[]) { + + int i,j,etifd,ret,offset; + unsigned char p[ETINIPACKETSIZE],ficdata[32*4],streamdata[684*8]; + char desc[256]; + char prevsync[3]={0x00,0x00,0x00}; + unsigned char ficf,nst,fp,mid,ficl; + unsigned short int fl,mnsc,crch; + unsigned short int crc; + unsigned int sstc; + unsigned char scid,tpl,l1; + unsigned short int sad[64],stl[64]; + + etifd=open(v[1],O_RDONLY); + + if (etifd == -1) { + printf("Cannot open %s\n",v[1]); + return -1; + } + + while (1) { + + ret=read(etifd,p,ETINIPACKETSIZE); + if (ret!=ETINIPACKETSIZE) { + printf("End of ETI\n"); + break; + } + + // SYNC + printbuf("SYNC",0,p,4,""); + + // SYNC - ERR + if (p[0]==0xFF) + strcpy(desc,"No error"); + else + strcpy(desc,"Error"); + printbuf("ERR",1,p,1,desc); + + // SYNC - FSYNC + + if (memcmp(prevsync,"\x00\x00\x00",3)==0) { + if ((memcmp(p+1,"\x07\x3a\xb6",3)==0)||(memcmp(p+1,"\xf8\xc5\x49",3)==0)) { + strcpy(desc,"OK"); + memcpy(prevsync,p+1,3); + } + else { + strcpy(desc,"Wrong FSYNC"); + memcpy(prevsync,"\x00\x00\x00",3); + } + } else if (memcmp(prevsync,"\x07\x3a\xb6",3)==0) { + if (memcmp(p+1,"\xf8\xc5\x49",3)!=0) { + strcpy(desc,"Wrong FSYNC"); + memcpy(prevsync,"\x00\x00\x00",3); + } else { + strcpy(desc,"OK"); + memcpy(prevsync,p+1,3); + } + } else if (memcmp(prevsync,"\xf8\xc5\x49",3)==0) { + if (memcmp(p+1,"\x07\x3a\xb6",3)!=0) { + strcpy(desc,"Wrong FSYNC"); + memcpy(prevsync,"\x00\x00\x00",3); + } else { + strcpy(desc,"OK"); + memcpy(prevsync,p+1,3); + } + } + printbuf("Sync FSYNC",1,p+1,3,desc); + + // LIDATA + printbuf("LDATA",0,NULL,0,""); + // LIDATA - FC + printbuf("FC - Frame Characterization field",1,p+4,4,""); + // LIDATA - FC - FCT + sprintf(desc,"%d",p[4]); + printbuf("FCT - Frame Count",2,p+4,1,desc); + // LIDATA - FC - FICF + ficf=(p[5] & 0x80) >> 7; + if (ficf == 1) { + sprintf(desc,"%d - FIC Information are present",ficf); + } + else { + sprintf(desc,"%d - FIC Information are not present",ficf); + } + + printbuf("FICF - Fast Information Channel Flag",2,NULL,0,desc); + // LIDATA - FC - NST + nst=p[5] & 0x7F; + sprintf(desc,"%d",nst); + printbuf("NST - Number of streams",2,NULL,0,desc); + // LIDATA - FC - FP + fp=(p[6] & 0xE0) >> 5; + sprintf(desc,"%d",fp); + printbuf("FP - Frame Phase",2,&fp,1,desc); + // LIDATA - FC - MID + mid=(p[6] & 0x18) >> 3; + if (mid != 0) + sprintf(desc,"Mode %d",mid); + else + sprintf(desc,"Mode 4"); + printbuf("MID - Mode Identity",2,&mid,1,desc); + // LIDATA - FC - FL + fl = (p[6] & 0x07) * 256 + p[7]; + sprintf(desc,"%d words",fl); + printbuf("FL - Frame Length",2,NULL,0,desc); + + if (ficf==0) + ficl=0; + else if (mid==3) + ficl=32; + else + ficl=24; + + // STC + printbuf("STC - Stream Characterisation",1,NULL,0,""); + + for (i=0;i<nst;i++) { + sprintf(desc,"Stream number %d",i); + printbuf("STC - Stream Characterisation",2,p+8+4*i,4,desc); + scid = (p[8+4*i] & 0xFC) >> 2; + sprintf(desc,"%d",scid); + printbuf("SCID - Sub-channel Identifier",3,NULL,0,desc); + sad[i] = (p[8+4*i] & 0x03) * 256 + p[9+4*i]; + sprintf(desc,"%d",sad[i]); + printbuf("SAD - Sub-channel Start Address",3,NULL,0,desc); + tpl = (p[10+4*i] & 0xFC) >> 2; + + if ((tpl & 0x20) >> 5 == 1) { + unsigned char opt, plevel; + char plevelstr[32]; + opt = (tpl & 0x16) >> 2; + plevel = (tpl & 0x03); + if (opt == 0x00) { + if (plevel == 0) + strcpy(plevelstr,"1-A, 1/4, 16 CUs"); + else if (plevel == 1) + strcpy(plevelstr,"2-A, 3/8, 8 CUs"); + else if (plevel == 2) + strcpy(plevelstr,"3-A, 1/2, 6 CUs"); + else if (plevel == 3) + strcpy(plevelstr,"4-A, 3/4, 4 CUs"); + } else if (opt == 0x01) { + if (plevel == 0) + strcpy(plevelstr,"1-B, 4/9, 27 CUs"); + else if (plevel == 1) + strcpy(plevelstr,"2-B, 4/7, 21 CUs"); + else if (plevel == 2) + strcpy(plevelstr,"3-B, 4/6, 18 CUs"); + else if (plevel == 3) + strcpy(plevelstr,"4-B, 4/5, 15 CUs"); + } else + sprintf(plevelstr,"Unknown option %d",opt); + sprintf(desc,"0x%02x - Equal Error Protection. %s",tpl,plevelstr); + } else { + unsigned char tsw,uepidx; + tsw = (tpl & 0x08); + uepidx = tpl & 0x07; + sprintf(desc,"0x%02x - Unequal Error Protection. Table switch %d, UEP index %d",tpl,tsw,uepidx); + } + printbuf("TPL - Sub-channel Type and Protection Level",3,NULL,0,desc); + stl[i] = (p[10+4*i] & 0x03) * 256 + p[11+4*i]; + sprintf(desc,"%d => %d kbit/s",stl[i],stl[i]*8/3); + printbuf("STL - Sub-channel Stream Length",3,NULL,0,desc); + } + + // EOH + printbuf("EOH - End Of Header",1,p+8+4*nst,4,""); + mnsc = p[8+4*nst]*256+p[8+4*nst+1]; + printbuf("MNSC - Multiplex Network Signalling Channel",2,p+8+4*nst,2,""); + + crch = p[8+4*nst+2]*256+p[8+4*nst+3]; + crc=0xffff; + + for (i=4;i<8+4*nst+2;i++) + crc=update_crc_ccitt(crc,p[i]); + crc=~crc; + if (crc == crch) + sprintf(desc,"CRC OK"); + else + sprintf(desc,"CRC Mismatch: %02x",crc); + + printbuf("Header CRC",2,p+8+4*nst+2,2,desc); + + // MST - FIC + if (ficf==1) { + int endmarker=0,figcount=0; + unsigned char *fib, *fig; + unsigned short int figcrc; + + memcpy(ficdata,p+12+4*nst,ficl*4); + sprintf(desc,"FIC Data (%d bytes)",ficl*4); + //printbuf(desc,1,ficdata,ficl*4,""); + printbuf(desc,1,NULL,0,""); + fib=p+12+4*nst; + for(i=0;i<ficl*4/32;i++) { + fig=fib; + endmarker=0; + figcount=0; + while (!endmarker) { + unsigned char figtype,figext,figlen; + figtype = (fig[0] & 0xE0) >> 5; + if (figtype != 7) { + figlen = fig[0] & 0x1F; + sprintf(desc,"FIG %d [%d bytes]",figtype,figlen); + printbuf(desc,3,fig+1,figlen,""); + decodeFIG(fig+1,figlen,figtype,4); + fig+=(figlen+1); + figcount+=(figlen+1); + if (figcount >= 29) + endmarker=1; + } else + endmarker=1; + } + figcrc=fib[30]*256+fib[31]; + crc=0xffff; + for (j=0;j<30;j++) + crc=update_crc_ccitt(crc,fib[j]); + crc=~crc; + if (crc == figcrc) + sprintf(desc,"FIB CRC OK"); + else + sprintf(desc,"FIB CRC Mismatch: %02x",crc); + + printbuf("FIB CRC",3,fib+30,2,desc); + fib+=32; + } + } + + offset=0; + for (i=0;i<nst;i++) { + memcpy(streamdata,p+12+4*nst+ficf*ficl*4+offset,stl[i]*8); + offset+=stl[i]*8; + sprintf(desc,"%d",i); + printbuf("Stream Data",1,streamdata,stl[i]*8,desc); + } + + // EOF + crch = p[12+4*nst+ficf*ficl*4+offset]*256+p[12+4*nst+ficf*ficl*4+offset+1]; + + crc=0xffff; + + for (i=12+4*nst;i<12+4*nst+ficf*ficl*4+offset;i++) + crc=update_crc_ccitt(crc,p[i]); + crc=~crc; + if (crc == crch) + sprintf(desc,"CRC OK"); + else + sprintf(desc,"CRC Mismatch: %02x",crc); + + printbuf("EOF",1,p+12+4*nst+ficf*ficl*4+offset,4,""); + printbuf("CRC",2,p+12+4*nst+ficf*ficl*4+offset,2,desc); + + //RFU + printbuf("RFU",2,p+12+4*nst+ficf*ficl*4+offset+2,2,""); + //TIST + l1 = (p[12+4*nst+ficf*ficl*4+offset+5] & 0xfe) >> 1; + sprintf(desc,"%d ms",l1*8); + printbuf("TIST - Time Stamp",1,p+12+4*nst+ficf*ficl*4+offset+4,4,desc); + + + + + + printf("-------------------------------------------------------------------------------------------------------------\n"); + } + +} + +void printbuf(char* h,int level, unsigned char* b, unsigned short int l, char* d) { + int i; + + for (i=0;i<level;i++) printf("\t"); + printf("%s",h); + if (l!=0) + printf(": "); + for (i=0;i<l;i++) { + printf("%02x ",b[i]); + } + if (strcmp(d,"") != 0) + printf(" [%s] ",d); + printf("\n"); + +} + + +void decodeFIG(unsigned char* f, unsigned char figlen,unsigned short int figtype, unsigned short int indent) { + + char desc[256]; + int i,j; + + switch (figtype) { + + case 0: { + unsigned short int ext,cn,oe,pd; + + cn = (f[0] & 0x80) >> 7; + oe = (f[0] & 0x40) >> 6; + pd = (f[0] & 0x20) >> 5; + ext = f[0] & 0x1F; + sprintf(desc,"FIG %d/%d: C/N=%d OE=%d P/D=%d",figtype,ext,cn,oe,pd); + printbuf(desc,indent,f+1,figlen-1,""); + switch (ext) { + + case 0: { + unsigned char cid,al,ch,hic,lowc,occ; + unsigned short int eid,eref; + + eid = f[1]*256+f[2]; + cid = (f[1] & 0xF0) >> 4; + eref = (f[1] & 0x0F)*256 + f[2]; + ch = (f[3] & 0xC0) >> 6; + al = (f[3] & 0x20) >> 5; + hic = f[3] & 0x1F; + lowc = f[4]; + if (ch != 0) { + occ = f[5]; + sprintf(desc,"Ensamble ID=0x%02x (Country id=%d, Ensamble reference=%d), Change flag=%d, Alarm flag=%d, CIF Count=%d/%d, Occurance change=%d",eid,cid,eref,ch,al,hic,lowc,occ); + } else + sprintf(desc,"Ensamble ID=0x%02x (Country id=%d, Ensamble reference=%d), Change flag=%d, Alarm flag=%d, CIF Count=%d/%d",eid,cid,eref,ch,al,hic,lowc); + printbuf(desc,indent+1,NULL,0,""); + + } + break; + case 2: { + unsigned short int sref, scid, sid; + unsigned char cid, ecc, local, caid, ncomp, timd, ps, ca, subchid, scty; + int k=1; + char psdesc[16]; + char sctydesc[32]; + + while (k<figlen) { + if (pd == 0) { + sid = f[k] * 256 + f[k+1]; + cid = (f[k] & 0xF0) >> 4; + sref = (f[k] & 0x0F) * 256 + f[k+1]; + k=k+2; + } else { + sid = f[k] * 256 * 256 * 256 + f[k+1] * 256 * 256 + f[k+2] * 256 + f[k+3]; + ecc = f[k]; + cid = (f[k+1] & 0xF0) >> 4; + sref = (f[k+1] & 0x0F) * 256 * 256 + f[k+2] * 256 + f[k+3]; + k=k+4; + } + + local = (f[k] & 0x80) >> 7; + caid = (f[k] & 0x70) >> 4; + ncomp = f[k] & 0x0F; + + if (pd == 0) + sprintf(desc,"Service ID=0x%02X (Country id=%d, Service referemce=%d), Number of components=%d, Local flag=%d, CAID=%d",sid,cid,sref,ncomp,local,caid); + else + sprintf(desc,"Service ID=0x%02X (ECC=%d, Country id=%d, Service referemce=%d), Number of components=%d, Local flag=%d, CAID=%d",sid,ecc,cid,sref,ncomp,local,caid); + printbuf(desc,indent+1,NULL,0,""); + + k++; + for (i=0;i<ncomp;i++) { + unsigned char scomp[2]; + + memcpy(scomp,f+k,2); + sprintf(desc,"Component[%d]",i); + printbuf(desc,indent+2,scomp,2,""); + timd = (scomp[0] & 0xC0) >> 6; + ps = (scomp[1] & 0x02) >> 1; + ca = scomp[1] & 0x01; + scty = scomp[0] & 0x3F; + subchid = (scomp[1] & 0xFC) >> 2; + + if (timd == 3) { + scid = scty*64 + subchid; + } + + if (ps == 0) + strcpy(psdesc,"Secondary service"); + else + strcpy(psdesc,"Primary service"); + + + if (timd == 0) { + //MSC stream audio + if (scty == 0) + sprintf(sctydesc,"MPEG Foreground sound (%d)",scty); + else if (scty == 1) + sprintf(sctydesc,"MPEG Background sound (%d)",scty); + else if (scty == 2) + sprintf(sctydesc,"Multi Chaneel sound (%d)",scty); + else if (scty == 63) + sprintf(sctydesc,"AAC sound (%d)",scty); + else + sprintf(sctydesc,"Unknown ASCTy (%d)",scty); + + sprintf(desc,"Stream audio mode, %s, %s, SubChannel ID=%02X, CA=%d",psdesc,sctydesc,subchid,ca); + printbuf(desc,indent+3,NULL,0,""); + } else if (timd == 1) { + //MSC stream data + sprintf(sctydesc,"DSCTy=%d",scty); + sprintf(desc,"Stream data mode, %s, %s, SubChannel ID=%02X, CA=%d",psdesc,sctydesc,subchid,ca); + printbuf(desc,indent+3,NULL,0,""); + } else if (timd == 2) { + // FIDC + sprintf(sctydesc,"DSCTy=%d",scty); + sprintf(desc,"FIDC mode, %s, %s, Fast Information Data Channel ID=%02X, CA=%d",psdesc,sctydesc,subchid,ca); + printbuf(desc,indent+3,NULL,0,""); + } else if (timd == 3) { + // MSC PAcket mode + sprintf(desc,"MSC Packet Mode, %s, Service Component ID=%02X, CA=%d",psdesc,subchid,ca); + printbuf(desc,indent+3,NULL,0,""); + } + k+=2; + } + } + } + + break; + + } + } + break; + + case 1: {// SHORT LABELS + unsigned short int ext,oe,charset; + unsigned short int flag; + char label[17]; + + + charset = (f[0] & 0xF0) >> 4; + oe = (f[0] & 0x80) >> 3; + ext = f[0] & 0x07; + sprintf(desc,"FIG %d/%d: OE=%d, Charset=%d",figtype,ext,oe,charset); + printbuf(desc,indent,f+1,figlen-1,""); + memcpy(label,f+figlen-18,16); + label[16]=0x00; + flag = f[figlen-2] * 256 +f[figlen-1]; + + switch (ext) { + + case 0: { // ENSAMBLE LABEL + unsigned short int eid; + eid = f[1] * 256 + f[2]; + sprintf(desc,"Ensamble ID 0x%04X label: \"%s\", Short label mask: 0x%04X",eid,label,flag); + printbuf(desc,indent+1,NULL,0,""); + } + break; + + case 1: { // Programme LABEL + unsigned short int sid; + sid = f[1] * 256 + f[2]; + sprintf(desc,"Service ID 0x%04X label: \"%s\", Short label mask: 0x%04X",sid,label,flag); + printbuf(desc,indent+1,NULL,0,""); + } + break; + + case 4: { // Service Component LABEL + unsigned int sid; + unsigned char pd,SCIdS; + pd = (f[1] & 0x80) >> 7; + SCIdS = f[1] & 0x0F; + if (pd==0) + sid = f[2] * 256 + f[3]; + else + sid = f[2] * 256 * 256 * 256 + f[3] * 256 * 256 + f[4] * 256 + f[5]; + sprintf(desc,"Service ID 0x%08X , Service Component ID 0x%04X Short, label: \"%s\", label mask: 0x%04X",sid,SCIdS,label,flag); + printbuf(desc,indent+1,NULL,0,""); + } + break; + + case 5: { // Data Service LABEL + unsigned int sid; + sid = sid = f[1] * 256 * 256 * 256 + f[2] * 256 * 256 + f[3] * 256 + f[4]; + sprintf(desc,"Service ID 0x%08X label: \"%s\", Short label mask: 0x%04X",sid,label,flag); + printbuf(desc,indent+1,NULL,0,""); + } + break; + + + case 6: { // X-PAD User Application label + unsigned int sid; + unsigned char pd,SCIdS,xpadapp; + char xpadappdesc[16]; + + pd = (f[1] & 0x80) >> 7; + SCIdS = f[1] & 0x0F; + if (pd==0) { + sid = f[2] * 256 + f[3]; + xpadapp = f[4] & 0x1F; + } + else { + sid = f[2] * 256 * 256 * 256 + f[3] * 256 * 256 + f[4] * 256 + f[5]; + xpadapp = f[6] & 0x1F; + } + + if (xpadapp==2) + strcpy(xpadappdesc,"DLS"); + else if (xpadapp==12) + strcpy(xpadappdesc,"MOT"); + + + sprintf(desc,"Service ID 0x%08X , Service Component ID 0x%04X Short, X-PAD App %02X (%s), label: \"%s\", label mask: 0x%04X",sid,SCIdS,xpadapp,xpadappdesc,label,flag); + printbuf(desc,indent+1,NULL,0,""); + } + break; + + + } + + } + break; + + + } + +} + diff --git a/lib_crc.c b/lib_crc.c new file mode 100644 index 0000000..26b6b99 --- /dev/null +++ b/lib_crc.c @@ -0,0 +1,459 @@ +#include "lib_crc.h" + + + + /*******************************************************************\ + * * + * Library : lib_crc * + * File : lib_crc.c * + * Author : Lammert Bies 1999-2008 * + * E-mail : info@lammertbies.nl * + * Language : ANSI C * + * * + * * + * Description * + * =========== * + * * + * The file lib_crc.c contains the private and public func- * + * tions used for the calculation of CRC-16, CRC-CCITT and * + * CRC-32 cyclic redundancy values. * + * * + * * + * Dependencies * + * ============ * + * * + * lib_crc.h CRC definitions and prototypes * + * * + * * + * Modification history * + * ==================== * + * * + * Date Version Comment * + * * + * 2008-04-20 1.16 Added CRC-CCITT calculation for Kermit * + * * + * 2007-04-01 1.15 Added CRC16 calculation for Modbus * + * * + * 2007-03-28 1.14 Added CRC16 routine for Sick devices * + * * + * 2005-12-17 1.13 Added CRC-CCITT with initial 0x1D0F * + * * + * 2005-05-14 1.12 Added CRC-CCITT with start value 0 * + * * + * 2005-02-05 1.11 Fixed bug in CRC-DNP routine * + * * + * 2005-02-04 1.10 Added CRC-DNP routines * + * * + * 1999-02-21 1.01 Added FALSE and TRUE mnemonics * + * * + * 1999-01-22 1.00 Initial source * + * * + \*******************************************************************/ + + + + /*******************************************************************\ + * * + * #define P_xxxx * + * * + * The CRC's are computed using polynomials. The coefficients * + * for the algorithms are defined by the following constants. * + * * + \*******************************************************************/ + +#define P_16 0xA001 +#define P_32 0xEDB88320L +#define P_CCITT 0x1021 +#define P_DNP 0xA6BC +#define P_KERMIT 0x8408 +#define P_SICK 0x8005 + + + + /*******************************************************************\ + * * + * static int crc_tab...init * + * static unsigned ... crc_tab...[] * + * * + * The algorithms use tables with precalculated values. This * + * speeds up the calculation dramaticaly. The first time the * + * CRC function is called, the table for that specific calcu- * + * lation is set up. The ...init variables are used to deter- * + * mine if the initialization has taken place. The calculated * + * values are stored in the crc_tab... arrays. * + * * + * The variables are declared static. This makes them invisi- * + * ble for other modules of the program. * + * * + \*******************************************************************/ + +static int crc_tab16_init = FALSE; +static int crc_tab32_init = FALSE; +static int crc_tabccitt_init = FALSE; +static int crc_tabdnp_init = FALSE; +static int crc_tabkermit_init = FALSE; + +static unsigned short crc_tab16[256]; +static unsigned long crc_tab32[256]; +static unsigned short crc_tabccitt[256]; +static unsigned short crc_tabdnp[256]; +static unsigned short crc_tabkermit[256]; + + + + /*******************************************************************\ + * * + * static void init_crc...tab(); * + * * + * Three local functions are used to initialize the tables * + * with values for the algorithm. * + * * + \*******************************************************************/ + +static void init_crc16_tab( void ); +static void init_crc32_tab( void ); +static void init_crcccitt_tab( void ); +static void init_crcdnp_tab( void ); +static void init_crckermit_tab( void ); + + + + /*******************************************************************\ + * * + * unsigned short update_crc_ccitt( unsigned long crc, char c ); * + * * + * The function update_crc_ccitt calculates a new CRC-CCITT * + * value based on the previous value of the CRC and the next * + * byte of the data to be checked. * + * * + \*******************************************************************/ + +unsigned short update_crc_ccitt( unsigned short crc, char c ) { + + unsigned short tmp, short_c; + + short_c = 0x00ff & (unsigned short) c; + + if ( ! crc_tabccitt_init ) init_crcccitt_tab(); + + tmp = (crc >> 8) ^ short_c; + crc = (crc << 8) ^ crc_tabccitt[tmp]; + + return crc; + +} /* update_crc_ccitt */ + + + + /*******************************************************************\ + * * + * unsigned short update_crc_sick( * + * unsigned long crc, char c, char prev_byte ); * + * * + * The function update_crc_sick calculates a new CRC-SICK * + * value based on the previous value of the CRC and the next * + * byte of the data to be checked. * + * * + \*******************************************************************/ + +unsigned short update_crc_sick( unsigned short crc, char c, char prev_byte ) { + + unsigned short short_c, short_p; + + short_c = 0x00ff & (unsigned short) c; + short_p = ( 0x00ff & (unsigned short) prev_byte ) << 8; + + if ( crc & 0x8000 ) crc = ( crc << 1 ) ^ P_SICK; + else crc = crc << 1; + + crc &= 0xffff; + crc ^= ( short_c | short_p ); + + return crc; + +} /* update_crc_sick */ + + + + /*******************************************************************\ + * * + * unsigned short update_crc_16( unsigned short crc, char c ); * + * * + * The function update_crc_16 calculates a new CRC-16 value * + * based on the previous value of the CRC and the next byte * + * of the data to be checked. * + * * + \*******************************************************************/ + +unsigned short update_crc_16( unsigned short crc, char c ) { + + unsigned short tmp, short_c; + + short_c = 0x00ff & (unsigned short) c; + + if ( ! crc_tab16_init ) init_crc16_tab(); + + tmp = crc ^ short_c; + crc = (crc >> 8) ^ crc_tab16[ tmp & 0xff ]; + + return crc; + +} /* update_crc_16 */ + + + + /*******************************************************************\ + * * + * unsigned short update_crc_kermit( unsigned short crc, char c ); * + * * + * The function update_crc_kermit calculates a new CRC value * + * based on the previous value of the CRC and the next byte * + * of the data to be checked. * + * * + \*******************************************************************/ + +unsigned short update_crc_kermit( unsigned short crc, char c ) { + + unsigned short tmp, short_c; + + short_c = 0x00ff & (unsigned short) c; + + if ( ! crc_tabkermit_init ) init_crckermit_tab(); + + tmp = crc ^ short_c; + crc = (crc >> 8) ^ crc_tabkermit[ tmp & 0xff ]; + + return crc; + +} /* update_crc_kermit */ + + + + /*******************************************************************\ + * * + * unsigned short update_crc_dnp( unsigned short crc, char c ); * + * * + * The function update_crc_dnp calculates a new CRC-DNP value * + * based on the previous value of the CRC and the next byte * + * of the data to be checked. * + * * + \*******************************************************************/ + +unsigned short update_crc_dnp( unsigned short crc, char c ) { + + unsigned short tmp, short_c; + + short_c = 0x00ff & (unsigned short) c; + + if ( ! crc_tabdnp_init ) init_crcdnp_tab(); + + tmp = crc ^ short_c; + crc = (crc >> 8) ^ crc_tabdnp[ tmp & 0xff ]; + + return crc; + +} /* update_crc_dnp */ + + + + /*******************************************************************\ + * * + * unsigned long update_crc_32( unsigned long crc, char c ); * + * * + * The function update_crc_32 calculates a new CRC-32 value * + * based on the previous value of the CRC and the next byte * + * of the data to be checked. * + * * + \*******************************************************************/ + +unsigned long update_crc_32( unsigned long crc, char c ) { + + unsigned long tmp, long_c; + + long_c = 0x000000ffL & (unsigned long) c; + + if ( ! crc_tab32_init ) init_crc32_tab(); + + tmp = crc ^ long_c; + crc = (crc >> 8) ^ crc_tab32[ tmp & 0xff ]; + + return crc; + +} /* update_crc_32 */ + + + + /*******************************************************************\ + * * + * static void init_crc16_tab( void ); * + * * + * The function init_crc16_tab() is used to fill the array * + * for calculation of the CRC-16 with values. * + * * + \*******************************************************************/ + +static void init_crc16_tab( void ) { + + int i, j; + unsigned short crc, c; + + for (i=0; i<256; i++) { + + crc = 0; + c = (unsigned short) i; + + for (j=0; j<8; j++) { + + if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_16; + else crc = crc >> 1; + + c = c >> 1; + } + + crc_tab16[i] = crc; + } + + crc_tab16_init = TRUE; + +} /* init_crc16_tab */ + + + + /*******************************************************************\ + * * + * static void init_crckermit_tab( void ); * + * * + * The function init_crckermit_tab() is used to fill the array * + * for calculation of the CRC Kermit with values. * + * * + \*******************************************************************/ + +static void init_crckermit_tab( void ) { + + int i, j; + unsigned short crc, c; + + for (i=0; i<256; i++) { + + crc = 0; + c = (unsigned short) i; + + for (j=0; j<8; j++) { + + if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_KERMIT; + else crc = crc >> 1; + + c = c >> 1; + } + + crc_tabkermit[i] = crc; + } + + crc_tabkermit_init = TRUE; + +} /* init_crckermit_tab */ + + + + /*******************************************************************\ + * * + * static void init_crcdnp_tab( void ); * + * * + * The function init_crcdnp_tab() is used to fill the array * + * for calculation of the CRC-DNP with values. * + * * + \*******************************************************************/ + +static void init_crcdnp_tab( void ) { + + int i, j; + unsigned short crc, c; + + for (i=0; i<256; i++) { + + crc = 0; + c = (unsigned short) i; + + for (j=0; j<8; j++) { + + if ( (crc ^ c) & 0x0001 ) crc = ( crc >> 1 ) ^ P_DNP; + else crc = crc >> 1; + + c = c >> 1; + } + + crc_tabdnp[i] = crc; + } + + crc_tabdnp_init = TRUE; + +} /* init_crcdnp_tab */ + + + + /*******************************************************************\ + * * + * static void init_crc32_tab( void ); * + * * + * The function init_crc32_tab() is used to fill the array * + * for calculation of the CRC-32 with values. * + * * + \*******************************************************************/ + +static void init_crc32_tab( void ) { + + int i, j; + unsigned long crc; + + for (i=0; i<256; i++) { + + crc = (unsigned long) i; + + for (j=0; j<8; j++) { + + if ( crc & 0x00000001L ) crc = ( crc >> 1 ) ^ P_32; + else crc = crc >> 1; + } + + crc_tab32[i] = crc; + } + + crc_tab32_init = TRUE; + +} /* init_crc32_tab */ + + + + /*******************************************************************\ + * * + * static void init_crcccitt_tab( void ); * + * * + * The function init_crcccitt_tab() is used to fill the array * + * for calculation of the CRC-CCITT with values. * + * * + \*******************************************************************/ + +static void init_crcccitt_tab( void ) { + + int i, j; + unsigned short crc, c; + + for (i=0; i<256; i++) { + + crc = 0; + c = ((unsigned short) i) << 8; + + for (j=0; j<8; j++) { + + if ( (crc ^ c) & 0x8000 ) crc = ( crc << 1 ) ^ P_CCITT; + else crc = crc << 1; + + c = c << 1; + } + + crc_tabccitt[i] = crc; + } + + crc_tabccitt_init = TRUE; + +} /* init_crcccitt_tab */ diff --git a/lib_crc.h b/lib_crc.h new file mode 100644 index 0000000..ea5ca76 --- /dev/null +++ b/lib_crc.h @@ -0,0 +1,66 @@ + /*******************************************************************\ + * * + * Library : lib_crc * + * File : lib_crc.h * + * Author : Lammert Bies 1999-2008 * + * E-mail : info@lammertbies.nl * + * Language : ANSI C * + * * + * * + * Description * + * =========== * + * * + * The file lib_crc.h contains public definitions and proto- * + * types for the CRC functions present in lib_crc.c. * + * * + * * + * Dependencies * + * ============ * + * * + * none * + * * + * * + * Modification history * + * ==================== * + * * + * Date Version Comment * + * * + * 2008-04-20 1.16 Added CRC-CCITT routine for Kermit * + * * + * 2007-04-01 1.15 Added CRC16 calculation for Modbus * + * * + * 2007-03-28 1.14 Added CRC16 routine for Sick devices * + * * + * 2005-12-17 1.13 Added CRC-CCITT with initial 0x1D0F * + * * + * 2005-02-14 1.12 Added CRC-CCITT with initial 0x0000 * + * * + * 2005-02-05 1.11 Fixed bug in CRC-DNP routine * + * * + * 2005-02-04 1.10 Added CRC-DNP routines * + * * + * 2005-01-07 1.02 Changes in tst_crc.c * + * * + * 1999-02-21 1.01 Added FALSE and TRUE mnemonics * + * * + * 1999-01-22 1.00 Initial source * + * * + \*******************************************************************/ + + + +#define CRC_VERSION "1.16" + + + +#define FALSE 0 +#define TRUE 1 + + + +unsigned short update_crc_16( unsigned short crc, char c ); +unsigned long update_crc_32( unsigned long crc, char c ); +unsigned short update_crc_ccitt( unsigned short crc, char c ); +unsigned short update_crc_dnp( unsigned short crc, char c ); +unsigned short update_crc_kermit( unsigned short crc, char c ); +unsigned short update_crc_sick( unsigned short crc, char c, char prev_byte ); |