jpnevulator-2.1.1/0000755000214200000620000000000012010014410013174 5ustar freddystaffjpnevulator-2.1.1/byte.c0000644000214200000620000000563212007305446014333 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #ifndef __USE_ISOC99 #define __USE_ISOC99 /* for newly introduced isblank() */ #endif #include #include "byte.h" /* Convert an ASCII character into a binary form. */ static char nibbleGet(char c) { return(isdigit(c)?c-'0':toupper(c)-'A'+0xA); } enum byteState { byteStateComplete=0, byteStateNibbleFirst, byteStateHexNotation, byteStateNibbleSecond, byteStateError }; int byteGet(FILE *fd) { int byte; enum byteState state; /* No real reason to do this, but it makes the compiler happy. If this next line is not here the compiler generates this warning below: byte.c:76:16: warning: ‘byte’ may be used uninitialized in this function [-Wuninitialized] So let's initialize byte anyway. */ byte=0; for(state=byteStateNibbleFirst;state!=byteStateComplete;) { static int character; switch(state) { case byteStateNibbleFirst: { character=fgetc(fd); if(isxdigit(character)) { byte=nibbleGet(character); if(character=='0') { state=byteStateHexNotation; } else { state=byteStateNibbleSecond; } } else if(!isblank(character)) { state=byteStateError; } break; } case byteStateHexNotation: { character=fgetc(fd); if(tolower(character)=='x') { state=byteStateNibbleFirst; } else { if(ungetc(character,fd)!=EOF) { state=byteStateNibbleSecond; } else { state=byteStateError; } } break; } case byteStateNibbleSecond: { character=fgetc(fd); if(isxdigit(character)) { byte=(byte<<4)+nibbleGet(character); state=byteStateComplete; } else { state=byteStateError; } break; } case byteStateError: { switch(character) { case EOF: { byte=byteRtrnEOF; break; } case '\n': { byte=byteRtrnEOL; break; } default: { byte=byteRtrnUnknown; break; } } state=byteStateComplete; break; } case byteStateComplete: { /* Do nothing, since it's impossible to reach this stage. Just * make the compiler happy. */ break; } } } return(byte); } jpnevulator-2.1.1/interface.c0000644000214200000620000001073411742603252015330 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include "options.h" #include "jpnevulator.h" #include "interface.h" #include "list.h" void interfaceInitialize(void) { listInitialize(&_jpnevulatorOptions.interface); } static int cmpr(void *p,void *q) { return(!strcasecmp(((struct interface *)p)->name,(char *)q)); } enum interfaceRtrn interfaceAdd(char *name,int (*interfaceOpen)(char *,int),int (*interfaceControlGet)(int,char *),void (*interfaceControlWrite)(FILE *,int),void (*interfaceClose)(int)) { struct interface *interface; int charactersPrinted; char error[256]; char *alias; /* Was an interface name given? */ if(name==NULL) { /* Nope. Since the interface name is optional for certain types of interfaces, make sure we have some sort of empty value to work with. */ name=""; } else { /* Is this interface already present in our list of interfaces? */ if(listSearch(&_jpnevulatorOptions.interface,cmpr,(void *)name)!=NULL) { return(interfaceRtrnDouble); } } interface=(struct interface *)malloc(sizeof(struct interface)); if(interface==NULL) { return(interfaceRtrnMemory); } /* Did the user give us an alias for the interface name? */ if((alias=strstr(name,_jpnevulatorOptions.aliasSeparator))!=NULL) { /* Yes, so split the alias from the name. */ *alias='\0'; /* Advance the alias to the real beginning of it. */ alias+=strlen(_jpnevulatorOptions.aliasSeparator); /* And put it in our alias reference. */ charactersPrinted=sprintf(interface->alias,"%.*s",(int)sizeof(interface->alias)-1,alias); if(charactersPrinted!=strlen(alias)) { fprintf(stderr,"%s: interface alias %s truncated to %d chars -> %s\n",PROGRAM_NAME,alias,charactersPrinted,interface->alias); } } else { /* No, empty the alias. */ strcpy(interface->alias,""); } charactersPrinted=sprintf(interface->name,"%.*s",(int)sizeof(interface->name)-1,name); if(charactersPrinted!=strlen(name)) { fprintf(stderr,"%s: interface %s truncated to %d chars -> %s\n",PROGRAM_NAME,name,charactersPrinted,interface->name); } interface->fd=interfaceOpen(interface->name,sizeof(interface->name)-1); if(interface->fd==-1) { sprintf(error,"%s: Unable to open interface %s",PROGRAM_NAME,interface->name); perror(error); return(interfaceRtrnOpen); } /* Initialize the byte count. We have not received/send any bytes yet. */ interface->byteCount=0UL; /* Put the control call-back in place and get the current state of the control bits if needed. */ interface->controlGet=interfaceControlGet; interface->controlWrite=interfaceControlWrite; if(boolIsSet(_jpnevulatorOptions.control)) { interface->control=interfaceControlGet(interface->fd,interface->name); } /* Add our interface to the list of interfaces. */ if(listAppend(&_jpnevulatorOptions.interface,(void *)interface)!=listRtrnOk) { fprintf(stderr,"%s: unable to add interface %s to the list of interfaces!\n",PROGRAM_NAME,interface->name); return(interfaceRtrnList); } /* Store a reference to the function to close this interface. */ interface->close=interfaceClose; /* Advance to this next position. so all interfaces will be inline with the order the user gave us. */ listNext(&_jpnevulatorOptions.interface); return(interfaceRtrnOk); } int interfaceControlGet(struct interface *interface) { return(interface->controlGet(interface->fd,interface->name)); } void interfaceControlWrite(struct interface *interface,FILE *output,int control) { interface->controlWrite(output,control); } static void garbageCollect(void *data) { struct interface *interface; interface=(struct interface *)data; interface->close(interface->fd); free(interface); } void interfaceDestroy(void) { listDestroy(&_jpnevulatorOptions.interface,garbageCollect); } jpnevulator-2.1.1/options.h0000644000214200000620000000326012007315165015062 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __OPTIONS_H #define __OPTIONS_H #include "list.h" #include "misc.h" enum checksumType { checksumTypeNone=0, checksumTypeChecksum, checksumTypeCrc16, checksumTypeCrc8 }; enum actionType { actionTypeNone=0, actionTypeRead, actionTypeWrite }; struct jpnevulatorOptions { enum checksumType checksum; unsigned int crc16Poly; unsigned char crc8Poly; bool_t checksumFuckup; char io[256]; list_t interface; int size; bool_t send; bool_t print; unsigned long delayLine; unsigned long delayByte; enum actionType action; int width; bool_t timingPrint; unsigned long timingDelta; bool_t ascii; char *aliasSeparator; bool_t byteCountDisplay; bool_t pass; bool_t control; unsigned long controlPoll; int count; }; enum optionsRtrn { optionsRtrnOk=0, optionsRtrnUsage, optionsRtrnVersion, optionsRtrnImpossible }; extern enum optionsRtrn optionsParse(int,char **); #endif jpnevulator-2.1.1/dependencies.in0000644000214200000620000000121011743317313016170 0ustar freddystaffmain.o: main.c jpnevulator.h options.h list.h misc.h options.o: options.c options.h list.h misc.h jpnevulator.h io.h crc16.h \ crc8.h interface.h tty.h pty.h jpnevulator.o: jpnevulator.c jpnevulator.h options.h list.h misc.h byte.h \ io.h interface.h checksum.h crc16.h crc8.h byte.o: byte.c byte.h interface.o: interface.c options.h list.h misc.h jpnevulator.h \ interface.h tty.o: tty.c jpnevulator.h options.h list.h misc.h interface.h tty.h pty.o: pty.c jpnevulator.h options.h list.h misc.h interface.h pty.h io.o: io.c io.h options.h list.h misc.h jpnevulator.h checksum.o: checksum.c crc16.o: crc16.c crc8.o: crc8.c list.o: list.c list.h jpnevulator-2.1.1/jpnevulator.c0000644000214200000620000004716312007555736015757 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include #include "jpnevulator.h" #include "byte.h" #include "io.h" #include "interface.h" #include "checksum.h" #include "crc16.h" #include "crc8.h" #include "misc.h" struct jpnevulatorOptions _jpnevulatorOptions; static void messageChecksumAdd(unsigned char *message,int *size) { unsigned short checksum; switch(_jpnevulatorOptions.checksum) { case checksumTypeCrc8: { checksum=crc8Calculate(message,*size); /* Really dirty trick to put a 0x0D (CR) at the end of the message. But * it's Friday afternoon and frankly I don't care to code this once in * a life time usage properly. */ checksum|=0x0D00; break; } case checksumTypeCrc16: { checksum=crc16Calculate(message,*size); break; } default: case checksumTypeChecksum: { checksum=checksumCalculate(message,*size); break; } } message[(*size)++]=checksum&0xFF; message[(*size)++]=(checksum>>8)&0xFF; } /* Nice way of leaving no traces... * ...the more we know, the more we return. */ #define jpnevulatorGarbageCollect() { \ interfaceDestroy(); \ if(input!=NULL) { \ ioClose(input); \ } \ if(message!=NULL) { \ free(message); \ } \ } enum jpnevulatorRtrn jpnevulatorWrite(void) { int byte; struct interface *interface; FILE *input=NULL; unsigned char *message=NULL; int index; int line; bool_t writingStart; /* Open our input file. */ input=ioOpen("r"); if(input==NULL) { perror(PROGRAM_NAME": Unable to open input"); jpnevulatorGarbageCollect(); return(jpnevulatorRtrnNoInput); } /* Allocate memory for the messages to send. */ message=(unsigned char *)malloc(sizeof(message[0])*_jpnevulatorOptions.size); if(message==NULL) { perror(PROGRAM_NAME": Unable to allocate memory for message"); jpnevulatorGarbageCollect(); return(jpnevulatorRtrnNoMessage); } /* By default we do not expect to start writing because we have reached the maximum amount (--count) of bytes. */ boolReset(writingStart); /* Collect and send the messages. We collect the messages byte by byte from the * input and send them on the line when we receive an end-of-line. Take notice of this rather strange test. We need to test for writingStart too, since it's possible the counter equals zero and we still need to write some bytes on the line. I myself will probably not understand why within a couple of months, hence this special remark. Not too many details, since I like to keep myself puzzeled every once in a while. ;) */ line=1; for(index=0;(boolIsSet(writingStart)||(_jpnevulatorOptions.count!=0))&&((byte=byteGet(input))!=byteRtrnEOF);) { if(boolIsSet(writingStart)) { byte=byteRtrnEOL; } switch(byte) { case byteRtrnEOL: { int n; /* Add a checksum to the message if requested. */ if(_jpnevulatorOptions.checksum!=checksumTypeNone) { messageChecksumAdd(message,&index); if(boolIsSet(_jpnevulatorOptions.checksumFuckup)) { /* Subtract one from the last checksum byte of the message if the user * request to fuck up the checksum. */ message[index-1]-=1; } } /* Send the message on the line. */ if(boolIsSet(_jpnevulatorOptions.send)) { if((interface=(struct interface *)listFirst(&_jpnevulatorOptions.interface))!=NULL) { do { /* Delay between bytes if requested. */ if(_jpnevulatorOptions.delayByte>0) { int byteIndex; for(byteIndex=0;byteIndexfd,&(message[byteIndex]),1); if(n<0) { fprintf(stderr,"%s: %s: write of line %d byte %d failed(%d).\n",PROGRAM_NAME,interfacePrint(interface),line,byteIndex,n); } usleep(_jpnevulatorOptions.delayByte); } } else { n=write(interface->fd,message,sizeof(message[0])*index); if(n<0) { fprintf(stderr,"%s: %s: write of line %d failed(%d).\n",PROGRAM_NAME,interfacePrint(interface),line,n); } } } while((interface=(struct interface *)listNext(&_jpnevulatorOptions.interface))!=NULL); } } /* Print the message if requested. */ if(boolIsSet(_jpnevulatorOptions.print)) { for(n=0;n0) { usleep(_jpnevulatorOptions.delayLine); } /* Make sure this is reset again, otherwise we will never stop reading from stdin even though we have already refused to write more data. :) */ boolReset(writingStart); /* Start again with a new message and increase the line counter. */ index=0; line++; break; } case byteRtrnUnknown: { /* Warn the user if we read invalid characters in the input file. We only give a warning and still * send the message. The user might now what he or she is doing :-) */ fprintf(stderr,"%s: invalid characters on input line %d. Message can be corrupted.\n",PROGRAM_NAME,line); break; } default: { /* Place the new input byte into the message. Check if there is enough room for * this new byte and do leave some room(2 bytes) for the checksum if necessary. * Nice trick ;-) */ if(index<(_jpnevulatorOptions.size-(_jpnevulatorOptions.checksum*2))) { message[index++]=byte; } else { fprintf(stderr,"%s: Input line %d too big. Increase message size (--size).\n",PROGRAM_NAME,line); } /* Do we count the amount of bytes to write and if so are we finished writing? */ if((_jpnevulatorOptions.count>0)&&(--_jpnevulatorOptions.count==0)) { boolSet(writingStart); } break; } } } /* Free allocated memory and close files opened. */ jpnevulatorGarbageCollect(); return(jpnevulatorRtrnOk); } #undef jpnevulatorGarbageCollect static void asciiWrite(FILE *output,char *ascii,int asciiSize,int *bytesWritten,bool_t fill) { if((*bytesWritten)!=0) { if(boolIsSet(_jpnevulatorOptions.ascii)) { if(boolIsSet(fill)) { int index; for(index=*bytesWritten;index<_jpnevulatorOptions.width;index++) { fprintf(output," "); } } fprintf(output,"\t%s",ascii); memset(ascii,'\0',asciiSize); } fprintf(output,"\n"); *bytesWritten=0; } } static void headerWrite( FILE *output, char *ascii,int asciiSize, int *bytesWritten, struct interface *interfaceReader,char *interfaceNameCopy,int interfaceNameCopySize, struct timeval *timeCurrent,struct timeval *timeLast ) { struct tm *time; *timeLast=*timeCurrent; gettimeofday(timeCurrent,NULL); if( boolIsSet(_jpnevulatorOptions.timingPrint)&& ((memcmp(interfaceNameCopy,interfaceReader->name,interfaceNameCopySize)!=0)|| (((((timeCurrent->tv_sec-timeLast->tv_sec)*1000000L)+timeCurrent->tv_usec)-timeLast->tv_usec)>_jpnevulatorOptions.timingDelta)) ) { asciiWrite(output,ascii,asciiSize,bytesWritten,boolTrue); time=localtime(&(timeCurrent->tv_sec)); fprintf( output, "%04d-%02d-%02d %02d:%02d:%02d.%06ld:", time->tm_year+1900,time->tm_mon+1,time->tm_mday, time->tm_hour,time->tm_min,time->tm_sec,timeCurrent->tv_usec ); /* If more than one interface is given we want it always to * be displayed as part of the printing of the timing. It's * way to confusing otherwise. */ if(listElements(&_jpnevulatorOptions.interface)>1) { fprintf(output," %s",interfacePrint(interfaceReader)); } memcpy(interfaceNameCopy,interfaceReader->name,interfaceNameCopySize); fprintf(output,"\n"); } else { if( (listElements(&_jpnevulatorOptions.interface)>1)&& (memcmp(interfaceNameCopy,interfaceReader->name,interfaceNameCopySize)!=0) ) { asciiWrite(output,ascii,asciiSize,bytesWritten,boolTrue); fprintf(output,"%s\n",interfacePrint(interfaceReader)); memcpy(interfaceNameCopy,interfaceReader->name,interfaceNameCopySize); } } } static void controlHandle( FILE *output, char *ascii,int asciiSize, int *bytesWritten, struct interface *interfaceReader,char *interfaceNameCopy,int interfaceNameCopySize, struct timeval *timeCurrent,struct timeval *timeLast ) { int control; control=interfaceControlGet(interfaceReader); if(control!=interfaceReader->control) { /* We need this explicit call to asciiWrite, even though headerWrite will call asciiWrite() itself probably. Yes, the probably means exactly what it says probably. It's possible that controlHandle() gets called and headerWrite() does not think it needs to write a new header and so no need to write the ascii data, but new control data will get written before the ascii data is written. That is, if the modem control bits change within the timing delta on an interface that has just received data. Blam, nasty output! This explicit call to asciiWrite() fixes that. */ asciiWrite(output,ascii,asciiSize,bytesWritten,boolTrue); headerWrite(output,ascii,asciiSize,bytesWritten,interfaceReader,interfaceNameCopy,interfaceNameCopySize,timeCurrent,timeLast); interfaceControlWrite(interfaceReader,output,control); interfaceReader->control=control; } } /* Nice way of leaving no traces... * ...the more we know, the more we return. */ #define jpnevulatorGarbageCollect() { \ interfaceDestroy(); \ if(output!=NULL) { \ ioClose(output); \ } \ if(message!=NULL) { \ free(message); \ } \ if(ascii!=NULL) { \ free(ascii); \ } \ } enum jpnevulatorRtrn jpnevulatorRead(void) { FILE *output=NULL; unsigned char *message=NULL; char *ascii=NULL; int asciiSize; ssize_t bytesRead; int bytesWritten; struct timeval timeCurrent,timeLast,*timeoutPtr,timeout; unsigned long *timeoutReference; int timeoutDelta,timeoutCount; fd_set readfdsReal,readfdsCopy; struct interface *interfaceReader,*interfaceWriter; char interfaceNameCopy[sizeof(interfaceReader->name)]; int nfds; /* Open our output file. */ output=ioOpen("w"); if(output==NULL) { perror(PROGRAM_NAME": Unable to open output"); jpnevulatorGarbageCollect(); return(jpnevulatorRtrnNoOutput); } /* Allocate memory for the messages to receive. */ message=(unsigned char *)malloc(sizeof(message[0])*_jpnevulatorOptions.size); if(message==NULL) { perror(PROGRAM_NAME": Unable to allocate memory for message"); jpnevulatorGarbageCollect(); return(jpnevulatorRtrnNoMessage); } /* Allocate memory for the ascii data to print if desired. */ if(boolIsSet(_jpnevulatorOptions.ascii)) { asciiSize=(sizeof(ascii[0])*_jpnevulatorOptions.width)+1; ascii=(char *)malloc(asciiSize); if(ascii==NULL) { perror(PROGRAM_NAME": Unable to allocate memory for ascii data"); jpnevulatorGarbageCollect(); return(jpnevulatorRtrnNoAscii); } memset(ascii,'\0',asciiSize); } else { /* No real reason to do this, but it makes the compiler happy. If this next line is not here the compiler generates this warning below: jpnevulator.c:407:19: warning: ‘asciiSize’ may be used uninitialized in this function [-Wuninitialized] So let's initialize asciiSize anyway. */ asciiSize=0; } /* Initialize our last time to be far enough from the current time. Far * enough is a little bit more than --timing-delta away from it. This way * our first data will always gets it's timing information if requested. Take * notice that I use timeCurrent here, since that one will be assigned to * timeLast before gettimeofday() in the loop. */ gettimeofday(&timeCurrent,NULL); timeCurrent.tv_sec-=(_jpnevulatorOptions.timingDelta/1000000L)+1; /* Setup our set of read file descriptors to watch. We set up the copy * so we don't have to parse our list of interfaces every time we iterate. */ FD_ZERO(&readfdsCopy); nfds=0; if((interfaceReader=(struct interface *)listFirst(&_jpnevulatorOptions.interface))!=NULL) { do { FD_SET(interfaceReader->fd,&readfdsCopy); nfds=max(nfds,interfaceReader->fd); } while((interfaceReader=(struct interface *)listNext(&_jpnevulatorOptions.interface))!=NULL); } else { fprintf(stderr,"%s: No available interface to read from\n",PROGRAM_NAME); jpnevulatorGarbageCollect(); return(jpnevulatorRtrnNoTTY); } /* Clear our copy of the interface name, so if multiple interfaces are * given it will print the first one and only on a change the name * of the interface will be printed. */ memset(interfaceNameCopy,'\0',sizeof(interfaceNameCopy)); /* Do we need a timeout? We only need this when we also display the ASCII * values for the received bytes. In that case we use the timeout to display * the ASCII values automatically, otherwise they will never appear when less * then the line length bytes are received and no more bytes are coming. * * And of course we need the timeout too when we poll for modem control bits. */ timeoutCount=0; timeoutDelta=0; if(boolIsSet(_jpnevulatorOptions.ascii)||boolIsSet(_jpnevulatorOptions.control)) { timeoutPtr=&timeout; /* What timeout shall we use? If only one of the two is activated use that one and otherwise use the smallest of the two. */ if(boolIsSet(_jpnevulatorOptions.ascii)&&boolIsSet(_jpnevulatorOptions.control)) { if(_jpnevulatorOptions.timingDelta<_jpnevulatorOptions.controlPoll) { timeoutReference=&_jpnevulatorOptions.timingDelta; timeoutDelta=(_jpnevulatorOptions.controlPoll/_jpnevulatorOptions.timingDelta)+1; } else { timeoutReference=&_jpnevulatorOptions.controlPoll; timeoutDelta=(_jpnevulatorOptions.timingDelta/_jpnevulatorOptions.controlPoll)+1; } } else if(boolIsSet(_jpnevulatorOptions.ascii)) { timeoutReference=&_jpnevulatorOptions.timingDelta; } else { timeoutReference=&_jpnevulatorOptions.controlPoll; } } else { timeoutPtr=NULL; } /* Receive our messages. */ bytesWritten=0; for(;_jpnevulatorOptions.count!=0;) { int index; int rtrn; /* Restore our set of read file descriptors. */ readfdsReal=readfdsCopy; if(timeoutPtr!=NULL) { timeoutPtr->tv_sec=(*timeoutReference)/1000000L; timeoutPtr->tv_usec=(*timeoutReference)%1000000L; } /* Wait and see if anything flows in. */ rtrn=select(nfds+1,&readfdsReal,NULL,NULL,timeoutPtr); if(rtrn==-1) { /* Forgotten why, but we do not do anything here. I once must have had a * very good reason, but I can't recall anymore. Let's just put in * another funny bullshit comment to give this all some kind of meaning. */ } else if(rtrn) { /* If we have received some data, we obviously need to reset out timeout counter. Otherwise it would be considered cheating. Forgetting to reset this counter results in a slight different interpretation of the --timing-delta option. Nice BUG, luckily found it myself. */ timeoutCount=0; /* Walk through all our interfaces and see what needs to be done. */ if((interfaceReader=(struct interface *)listFirst(&_jpnevulatorOptions.interface))!=NULL) { do { if(FD_ISSET(interfaceReader->fd,&readfdsReal)) { int size; /* How many bytes should we read? */ if((_jpnevulatorOptions.count>0)&&(_jpnevulatorOptions.count<_jpnevulatorOptions.size)) { /* We need less bytes than the input buffer can handle, so only take what needed. */ size=_jpnevulatorOptions.count; } else { /* Take as many as possible. No limit set or not yet within reach. */ size=_jpnevulatorOptions.size; } bytesRead=read(interfaceReader->fd,message,size); if(bytesRead>0) { /* Are we counting bytes and if so subtract the amount just read. */ if(_jpnevulatorOptions.count>0) { _jpnevulatorOptions.count-=bytesRead; } headerWrite(output,ascii,asciiSize,&bytesWritten,interfaceReader,interfaceNameCopy,sizeof(interfaceNameCopy),&timeCurrent,&timeLast); for(index=0;index=_jpnevulatorOptions.width) { asciiWrite(output,ascii,asciiSize,&bytesWritten,boolFalse); } else if(bytesWritten!=0) { fprintf(output," "); } if((bytesWritten==0)&&boolIsSet(_jpnevulatorOptions.byteCountDisplay)) { fprintf(output,"%08lX\t",interfaceReader->byteCount); } fprintf(output,"%02X",message[index]); /* Increase the byte count for this interface. */ interfaceReader->byteCount++; if(boolIsSet(_jpnevulatorOptions.ascii)) { ascii[bytesWritten]=isprint(message[index])?message[index]:'.'; } bytesWritten++; } /* Does the user want to pass the data between all the interfaces? */ if(boolIsSet(_jpnevulatorOptions.pass)) { struct listElement *interfaceListPosition; /* Save the current position in the interface list, since we are about to traverse it again. */ interfaceListPosition=listCurrentPositionSave(&_jpnevulatorOptions.interface); /* Traverse the interface list again in search for all the other (not this read) interface. For * every interface found write the read message to it. */ if((interfaceWriter=(struct interface *)listFirst(&_jpnevulatorOptions.interface))!=NULL) { do { if(interfaceWriter->fd!=interfaceReader->fd) { ssize_t n; n=write(interfaceWriter->fd,message,bytesRead); if(n<0) { fprintf(stderr,"%s: %s: write of %ld bytes failed(%ld).\n",PROGRAM_NAME,interfacePrint(interfaceWriter),bytesRead,n); } } } while((interfaceWriter=(struct interface *)listNext(&_jpnevulatorOptions.interface))!=NULL); } /* Restore the current position for the interface list again. */ listCurrentPositionLoad(&_jpnevulatorOptions.interface,interfaceListPosition); } fflush(output); } } /* See if we need to write some control data. */ if(boolIsSet(_jpnevulatorOptions.control)) { controlHandle(output,ascii,asciiSize,&bytesWritten,interfaceReader,interfaceNameCopy,sizeof(interfaceNameCopy),&timeCurrent,&timeLast); } } while((_jpnevulatorOptions.count!=0)&&((interfaceReader=(struct interface *)listNext(&_jpnevulatorOptions.interface))!=NULL)); } } else { /* Another timeout! Do we already need to write our ASCII data? */ if(timeoutCount>=timeoutDelta) { asciiWrite(output,ascii,asciiSize,&bytesWritten,boolTrue); timeoutCount=0; } else { timeoutCount++; } /* See if we need to write some control data. */ if(boolIsSet(_jpnevulatorOptions.control)) { if((interfaceReader=(struct interface *)listFirst(&_jpnevulatorOptions.interface))!=NULL) { do { controlHandle(output,ascii,asciiSize,&bytesWritten,interfaceReader,interfaceNameCopy,sizeof(interfaceNameCopy),&timeCurrent,&timeLast); } while((interfaceReader=(struct interface *)listNext(&_jpnevulatorOptions.interface))!=NULL); } } } } /* Might we possibly still need to write our ASCII data? */ asciiWrite(output,ascii,asciiSize,&bytesWritten,boolTrue); /* And if we didn't wrote our ASCII data we most probably need a newline. */ if(bytesWritten!=0) { fprintf(output,"\n"); } /* Close files opened. */ jpnevulatorGarbageCollect(); return(jpnevulatorRtrnOk); } #undef jpnevulatorGarbageCollect jpnevulator-2.1.1/pty.c0000644000214200000620000000373511742602660014211 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define _XOPEN_SOURCE 600 #include #include #include #include #include #include #include "jpnevulator.h" #include "interface.h" #include "pty.h" static int ptyOpen(char *name,int length) { int fd; fd=posix_openpt(O_RDWR); if(fd!=-1) { char *pts; int charactersPrinted; grantpt(fd); unlockpt(fd); pts=ptsname(fd); fprintf(stderr,"%s: slave pts device is %s.\n",PROGRAM_NAME,pts); charactersPrinted=sprintf(name,"%.*s",length,pts); if(charactersPrinted!=strlen(name)) { fprintf(stderr,"%s: interface %s truncated to %d chars -> %s\n",PROGRAM_NAME,pts,charactersPrinted,name); } } return(fd); } static int ptyControlGet(int fd,char *name) { /* A pty does not have modem control bits, so we simply return 0. This way the interface plays nicely according to general rules and never produces any output. */ return(0); } static void ptyControlWrite(FILE *output,int control) { /* We don't do anything and cowardly refuse to write anything. */ } static void ptyClose(int fd) { close(fd); } enum interfaceRtrn ptyAdd(char *name) { return(interfaceAdd(name,ptyOpen,ptyControlGet,ptyControlWrite,ptyClose)); } jpnevulator-2.1.1/pty.h0000644000214200000620000000157311714040765014215 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __PTY_H #define __PTY_H extern enum interfaceRtrn ptyAdd(char *); #endif jpnevulator-2.1.1/crc8.c0000644000214200000620000000235311706642723014233 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ static int _poly=0x07; void crc8PolyInit(unsigned char poly) { _poly=poly; } unsigned char crc8Calculate(unsigned char *mssg,int size) { unsigned char crc=0; unsigned char crcReversed=0; int index; for(index=0;index>7)^((mssg[index>>3]>>(index&7))&1)) { crc=(crc<<1)^_poly; } else { crc<<=1; } } for(index=0;index<8;index++) { crcReversed=(crcReversed<<1)|((crc>>index)&1); } return(crcReversed); } jpnevulator-2.1.1/Changelog0000644000214200000620000001040212010014405015007 0ustar freddystaffjpnevulator (2.1.1); urgency=low * Fixed segmentation fault using -o option and checked if any other option had the same problem, which of course turned out to be the case. -- Freddy Spierenburg Mon, 06 Aug 2012 21:20:35 +0200 jpnevulator (2.1.0); urgency=low * Fixed lintian problems. * Added support for --count option. This makes the software exit after reading / writing the given amount of bytes. -- Freddy Spierenburg Sun, 05 Aug 2012 22:47:38 +0200 jpnevulator (2.0.3); urgency=low * Fixed help output, --control-enable should be --control and options should be using a '=' character in between option and value. Thanks to Gustavo Conrad for sending me a bug report! -- Freddy Spierenburg Wed, 09 May 2012 21:25:05 +0200 jpnevulator (2.0.2); urgency=low * Fixed small --timing-delta bug. -- Freddy Spierenburg Tue, 17 Apr 2012 18:51:18 +0200 jpnevulator (2.0.1); urgency=low * This time increased the software version number for real. :( * Fixed a small time output bug. -- Freddy Spierenburg Mon, 16 Apr 2012 18:25:08 +0200 jpnevulator (2.0.0); urgency=low * Added pseudo-terminal device support. * Added support to monitor modem control bits. * Fixed typo in manual page. -- Freddy Spierenburg Sun, 15 Apr 2012 23:26:33 +0200 jpnevulator (1.3.1); urgency=low * Fixed spelling error in TODO file. * Fixed typo in manual page. * Fixed typo and current home address in README file. * Fixed many many Debian lintian errors and even some compile warnings. * Finally added a FAQ file. -- Freddy Spierenburg Sat, 21 Jan 2012 23:54:20 +0100 jpnevulator (1.3.0); urgency=low * Added the --pass option. A great idea mailed to me by Ardor. * Nicely use bool_t in a consequent manner. * Fixed a stupid typo bug in tty.h. It only became a compiler bug * since I now changed the tty variable into ttyReader. Stupid me! -- Freddy Spierenburg Wed, 22 Apr 2009 19:08:22 +0200 jpnevulator (1.2.3); urgency=low * Fixed some typo's in debian/control. * FIxed some typo's in the manual page and the files BUGS and README. -- Freddy Spierenburg Fri, 21 Jul 2006 15:17:52 +0200 jpnevulator (1.2.2); urgency=low * Fixed some compiler warnings; isblank() and combination printf() and sizeof(). -- Freddy Spierenburg Mon, 17 Jul 2006 00:04:54 +0200 jpnevulator (1.2.1); urgency=low * Compressed manual page with best compression. * Changed description in Debian control file. -- Freddy Spierenburg Sun, 25 Jun 2006 16:06:32 +0200 jpnevulator (1.2.0); urgency=low * Fixed small bug in list.c; listDestory() should also zero the number of elements in the list. * Fixed a bug; the --byte-count option now works correct. * Added a timeout for the display of ASCII data. -- Freddy Spierenburg Sun, 25 Jun 2006 14:05:43 +0200 jpnevulator (1.1.0); urgency=low * Added support for --delay-byte. This option waits the given amount of microseconds in between the sending of every input byte. * Renamed the --delay option to --delay-line. -- Freddy Spierenburg Sat, 03 Jun 2006 10:54:03 +0200 jpnevulator (1.0.3); urgency=low * Added support for --byte-count. This option writes a nice index number of the bytes received. * Written a nice manual page. -- Freddy Spierenburg Sat, 03 Jun 2006 02:41:12 +0200 jpnevulator (1.0.2); urgency=medium * Added support for aliasing of the tty names in the printing. Just give --tty "/dev/ttyS0:Motorola MTM800" and the printing of data will use Motorola MTM800 instead of /dev/ttyS0. If you need another separator then ':' use the --alias-separator option. Any string of characters can be used. -- Freddy Spierenburg Thu, 01 Jun 2006 21:42:09 +0200 jpnevulator (1.0.1); urgency=medium * Bugfix. Using one tty the --timing-print option didn't worked correctly anymore. -- Freddy Spierenburg Thu, 01 Jun 2006 11:35:10 +0200 jpnevulator (1.0.0); urgency=low * Initial release. -- Freddy Spierenburg Tue, 30 May 2006 21:56:54 +0200 jpnevulator-2.1.1/BUGS0000644000214200000620000000372410460153744013712 0ustar freddystaffBUGS ==== This file describes several bugs known as of today. There do exist probably some more, but I'm not aware of them right now. Do not hesitate to send me your bug-reports though. I will gladly add them to this file and maybe even solve some of them. :-) Order of bytes broke when reading several tty devices at once ============================================================= The display of incoming bytes can be broke if you use multiple tty devices to read from. At the moment I do not have a solution for this problem. Since I use select() to watch the several tty devices and after the select() I have to read() them one by one, I can not completely 100% display which bytes came after which on different tty devices. Take the example below: $ jpnevulator --ascii --timing-print --tty /dev/ttyS0 --tty /dev/ttyUSB0 --read 2006-05-30 13:23:49.461075: /dev/ttyS0 00 00 05 3B 0D 00 00 05 ...;.... 2006-05-30 13:23:49.461113: /dev/ttyUSB0 00 05 3B 0D 00 00 05 3B 0D ..;....;. 2006-05-30 13:23:49.473074: /dev/ttyS0 3B 0D 00 00 05 3B 0D ;....;. 2006-05-30 13:23:49.473105: /dev/ttyUSB0 00 12 05 06 39 00 12 05 06 39 1F 00 22 80 00 0E ....9....9.."... $ And now see the order in which things really got sent on the line: /dev/ttyS0: 00 00 05 3B 0D /dev/ttyUSB0: 00 00 05 3B 0D /dev/ttyS0: 00 00 05 3B 0D /dev/ttyUSB0: 00 00 05 3B 0D /dev/ttyS0: 00 00 05 3B 0D /dev/ttyUSB0: 00 00 05 3B 0D 00 12 05 06 39 00 12 05 06 39 ... As you can see /dev/ttyUSB0 receives the echo of all things sent by /dev/ttyS0. This is exactly what happens. But since there does exist a small time between the select() who is happy expressing something is available and the read() who does get the available data, some extra data will be available. I have no idea on how I can use high level system call like select() and read() and be still able to put the bytes in the correct order. Anyone an idea? jpnevulator-2.1.1/crc16.h0000644000214200000620000000173011706642720014312 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CRC16_H #define __CRC16_H extern void crc16TableCreate(unsigned short,unsigned short); extern unsigned short crc16Calculate(unsigned char *,unsigned short); #endif jpnevulator-2.1.1/options.c0000644000214200000620000002477112010014175015056 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include "options.h" #include "jpnevulator.h" #include "io.h" #include "crc16.h" #include "crc8.h" #include "list.h" #include "interface.h" #include "tty.h" #include "pty.h" static void usage(void) { printf( "Usage: %s [--version] [--help] [--checksum] [--crc16=poly]\n" " [--crc8=poly] [--fuck-up] [--file=file] [--no-send]\n" " [--delay-line=microseconds] [--delay-byte=microseconds]\n" " [--print] [--size=size] [--tty=tty] [--pty [=alias]] [--width] [--pass]\n" " [--read] [--write] [--timing-print] [--timing-delta=microseconds]\n" " [--ascii] [--alias-separator=separator] [--byte-count]\n" " [--control] [--control-poll=microseconds] [--count=bytes] \n", PROGRAM_NAME ); } static void optionsDefault(void) { /* Don't add a checksum by default. */ _jpnevulatorOptions.checksum=checksumTypeNone; /* Use the crc16 x^16+x^15+x^2+1 polynomial by default. */ _jpnevulatorOptions.crc16Poly=0xA001; crc16TableCreate(0,_jpnevulatorOptions.crc16Poly); /* Use the crc8 x^8+x^2+x+1 polynomial by default. */ _jpnevulatorOptions.crc8Poly=0x07; crc8PolyInit(_jpnevulatorOptions.crc8Poly); /* Don't fuck up the checksum(wrongly named crc) by default. */ boolReset(_jpnevulatorOptions.checksumFuckup); /* Read/Write standard input/output by default, but use some black magic to find out if a user selects * multiple I/O sources. Which we of course neglect anyway. */ sprintf(_jpnevulatorOptions.io,"%.*s",(int)sizeof(_jpnevulatorOptions.io)-1,ioMAGIC); /* Initialize the list where we store our interfaces. We do not yet add * the default interface. We postpone that up untill we know for sure the user * did not gave us any interface. */ interfaceInitialize(); /* By default we expect to send/receive Cham2 messages. */ _jpnevulatorOptions.size=22; /* By default we send our messages on the serial port... */ boolSet(_jpnevulatorOptions.send); /* ...but we probably don't want to see the messages on the console. Or do we? :-) */ boolReset(_jpnevulatorOptions.print); /* Do not delay between messages by default. */ _jpnevulatorOptions.delayLine=0L; /* Do not delay between bytes by default. */ _jpnevulatorOptions.delayByte=0L; /* Action type is mandatory (not by getopts, but by our own mechanism). */ _jpnevulatorOptions.action=actionTypeNone; /* By default we display 16 bytes on one line. */ _jpnevulatorOptions.width=16; /* By default we do not display timing information. */ boolReset(_jpnevulatorOptions.timingPrint); /* By default we couple bytes that arrive within 100 miliseconds. */ _jpnevulatorOptions.timingDelta=100000UL; /* By default we do not display ascii data in read mode. */ boolReset(_jpnevulatorOptions.ascii); /* By default the alias separator is the ':' character. */ _jpnevulatorOptions.aliasSeparator=":"; /* Do not show the byte count by default. */ boolReset(_jpnevulatorOptions.byteCountDisplay); /* Do not pass bytes between interfaces by default. */ boolReset(_jpnevulatorOptions.pass); /* Do not poll modem control bits by default. */ boolReset(_jpnevulatorOptions.control); /* Poll every milisecond by default (should suffice for 9600bps). */ _jpnevulatorOptions.controlPoll=1000UL; /* By default we read/write endlessly up untill the end of time. */ _jpnevulatorOptions.count=-1; } static void optionsIOWrite(char *file) { int charactersPrinted; charactersPrinted=sprintf(_jpnevulatorOptions.io,"%.*s",(int)sizeof(_jpnevulatorOptions.io)-1,file); if(charactersPrinted!=strlen(file)) { fprintf(stderr,"%s: Filename truncated to %d chars\n",PROGRAM_NAME,charactersPrinted); } } enum optionsRtrn optionsParse(int argc,char **argv) { int finished; optionsDefault(); for(finished=0;!finished;) { int option,option_index; static struct option long_options[]={ {"ascii",no_argument,NULL,'a'}, {"byte-count",no_argument,NULL,'b'}, {"checksum",no_argument,NULL,'c'}, {"control",no_argument,NULL,'C'}, {"control-poll",required_argument,NULL,'D'}, {"delay-line",required_argument,NULL,'d'}, {"timing-delta",required_argument,NULL,'e'}, {"file",required_argument,NULL,'f'}, {"timing-print",no_argument,NULL,'g'}, {"help",no_argument,NULL,'h'}, {"width",required_argument,NULL,'i'}, {"fuck-up",no_argument,NULL,'j'}, {"delay-byte",required_argument,NULL,'k'}, {"alias-separator",required_argument,NULL,'l'}, {"no-send",no_argument,NULL,'n'}, {"count",required_argument,NULL,'o'}, {"pass",no_argument,NULL,'P'}, {"print",no_argument,NULL,'p'}, {"pty",optional_argument,NULL,'q'}, {"read",no_argument,NULL,'r'}, {"size",required_argument,NULL,'s'}, {"tty",required_argument,NULL,'t'}, {"version",no_argument,NULL,'v'}, {"write",no_argument,NULL,'w'}, {"crc16",optional_argument,NULL,'y'}, {"crc8",optional_argument,NULL,'z'}, {NULL,no_argument,NULL,0} }; option=getopt_long(argc,argv,"abcCd:D:e:f:ghi:jk:l:no:pPq:rs:t:vwy:z:",long_options,&option_index); switch(option) { case -1: { finished=!finished; break; } case 'a': { boolSet(_jpnevulatorOptions.ascii); break; } case 'b': { boolSet(_jpnevulatorOptions.byteCountDisplay); break; } case 'c': { _jpnevulatorOptions.checksum=checksumTypeChecksum; break; } case 'C': { boolSet(_jpnevulatorOptions.control); break; } case 'd': { unsigned long delay; delay=atol(optarg); if(delay>0) { _jpnevulatorOptions.delayLine=delay; } else { fprintf(stderr,"%s: Discarding line delay. It should be bigger than zero.\n",PROGRAM_NAME); } break; } case 'D': { unsigned long poll; poll=atol(optarg); if(poll>0) { _jpnevulatorOptions.controlPoll=poll; } else { fprintf(stderr,"%s: Discarding control poll. It should be bigger than zero.\n",PROGRAM_NAME); } break; } case 'e': { _jpnevulatorOptions.timingDelta=atol(optarg); break; } case 'f': { optionsIOWrite(optarg); break; } case 'g': { boolSet(_jpnevulatorOptions.timingPrint); break; } case 'h': { usage(); return(optionsRtrnUsage); } case 'i': { int width; width=atoi(optarg); if(optarg>0) { _jpnevulatorOptions.width=width; } else { fprintf(stderr,"%s: Discarding width. It should be bigger than zero.\n",PROGRAM_NAME); } break; } case 'j': { boolSet(_jpnevulatorOptions.checksumFuckup); break; } case 'k': { unsigned long delay; delay=atol(optarg); if(delay>0) { _jpnevulatorOptions.delayByte=delay; } else { fprintf(stderr,"%s: Discarding byte delay. It should be bigger than zero.\n",PROGRAM_NAME); } break; } case 'l': { _jpnevulatorOptions.aliasSeparator=optarg; break; } case 'n': { boolReset(_jpnevulatorOptions.send); break; } case 'o': { int count; count=atoi(optarg); if(optarg>0) { _jpnevulatorOptions.count=count; } else { fprintf(stderr,"%s: Discarding count. It should be bigger than zero.\n",PROGRAM_NAME); } break; } case 'p': { boolSet(_jpnevulatorOptions.print); break; } case 'P': { boolSet(_jpnevulatorOptions.pass); break; } case 'q': { ptyAdd(optarg); break; } case 'r': { if(_jpnevulatorOptions.action!=actionTypeNone) { fprintf(stderr,"%s: Use --read or --write, but not both. Performing a read this time.\n",PROGRAM_NAME); } _jpnevulatorOptions.action=actionTypeRead; break; } case 's': { int size; size=atoi(optarg); if(size>0) { _jpnevulatorOptions.size=size; } else { fprintf(stderr,"%s: Discarding size. It should be bigger than zero.\n",PROGRAM_NAME); } break; } case 't': { ttyAdd(optarg); break; } case 'v': { printf( "%s version %s\n" "Copyright (C) 2006-2012 Freddy Spierenburg \n" "This is free software. You may redistribute copies of it under the terms of\n" "the GNU General Public License .\n" "There is NO WARRANTY, to the extent permitted by law.\n", PROGRAM_NAME,PROGRAM_VERSION ); return(optionsRtrnVersion); } case 'w': { if(_jpnevulatorOptions.action!=actionTypeNone) { fprintf(stderr,"%s: Use --read or --write, but not both. Performing a write this time.\n",PROGRAM_NAME); } _jpnevulatorOptions.action=actionTypeWrite; break; } case 'y': { _jpnevulatorOptions.checksum=checksumTypeCrc16; if(optarg) { printf("[%s]\n",optarg); _jpnevulatorOptions.crc16Poly=strtol(optarg,NULL,16); crc16TableCreate(0,_jpnevulatorOptions.crc16Poly); } break; } case 'z': { _jpnevulatorOptions.checksum=checksumTypeCrc8; if(optarg) { _jpnevulatorOptions.crc8Poly=strtol(optarg,NULL,16); crc8PolyInit(_jpnevulatorOptions.crc8Poly); } break; } } } /* As mentioned more early, we read/write standard input/output by default and warn the user if he * or she tries to use multiple sources. */ if(optind .SH DESCRIPTION .PP jpnevulator is a handy serial sniffer. You can use it to send data on a serial device too. You can read or write from/to one or more serial devices at the same time. .PP In write (\-\-write) mode data to be sent on the serial device(s) is read from a file or stdin in hexadecimal notation. The input format is FD or 0xFD. Of course all input is treated case-insensitive. Spaces may or may not be included in the input. So DEADBEEF is exactly the same as DE AD BE EF. Data is sent on the serial device(s) line by line. .PP In read (\-\-read) mode data to be read from the serial device(s) is written to a file or stdout in hexadecimal notation. Skim through the options for several enhancements in the output. It's even possible to pass(\-\-pass) on the data between the several serial devices. .PP Mandatory arguments to long options are mandatory for short options too. .PP Generic options: .TP \fB\-l\fR, \fB\-\-alias\-separator\fR Use the given string as the alias separator. See \-\-tty for more information. .TP \fB\-f\fR, \fB\-\-file\fR=\fINAME\fR In write mode read the contents of the file given and send them on the serial device(s) and in read mode write the contents of the serial device(s) to the file given. .TP \fB\-h\fR, \fB\-\-help\fR Shows a brief list of options. .TP \fB\-o\fR, \fB\-\-count\fR=\fIBYTES\fR Exit after reading / writing the given amount of bytes. .TP \fB\-r\fR, \fB\-\-read\fR Put the program in read mode. This way you read the data from the given serial device(s) and write it to the file given or stdout if none given. See the read options section for more read specific options. .TP \fB\-t\fR, \fB\-\-tty\fR=\fINAME:ALIAS\fR The serial device to read from or write to. Use multiple times to read/write from/to more than one serial device(s). For handy reference you can also separate an alias from the tty name with a collon ':'. If a collon is for some strange reason part of your device name, you can use the \-\-alias\-separator option to specify another separation string. If an alias is given it will be used as the name of the serial device. .TP \fB\-v\fR, \fB\-\-version\fR Output the version information, a small GPL notice and exit. .TP \fB\-w\fR, \fB\-\-write\fR Put the program in write mode. This way you read data from a given file or stdin if none given and write it to the serial device(s) given. See the write options section for more write specific options. .PP Read options: .TP \fB\-a\fR, \fB\-\-ascii\fR Besides the hexadecimal output also display an extra column with the data in the ASCII representation. Non printable characters are displayed as a dot '.'. The ASCII data is displayed after the hexadecimal data. .TP \fB\-b\fR, \fB\-\-byte\-count\fR Besides the hexadecimal output also display an extra column with the current index number of the byte in the output. These numbers are displayed in front of the hexadecimal data. When readin from multiple serial devices at the same time the index number will increase per serial device. .TP \fB\-C\fR, \fB\-\-control\fR Monitor modem control bits (line enable, data terminal ready, request to send, secondary TXD, secondary RXD, clear to send, carrier detect, ring and data set ready) too and notify changes. Use the \-\-control\-poll option to specify how often to poll for the bits. .TP \fB\-D\fR, \fB\-\-control\-poll\fR=\fIMICROSECONDS\fR The control poll is the amount of microseconds to wait in between two checks of the modem control bits if nothing else is happening. .TP \fB\-P\fR, \fB\-\-pass\fR This one passes all the data between the serial devices. Handy if you want to put your serial sniffer in between the serial devices you want to sniff. .TP \fB\-q\fR, \fB\-\-pty\fR=\fI:ALIAS\fR The pseudo-terminal device to read from. Use multiple times to read from more than one pseudo-terminal device(s). For handy reference you can also use an alias to name the pty. Make sure it starts with a collon ':'. Use the \-\-alias\-separator option if you for some reason don't like to use a collon. If an alias is given it will be used as the name of the pseudo-terminal device. .TP \fB\-e\fR, \fB\-\-timing\-delta\fR=\fIMICROSECONDS\fR The timing delta is the amount of microseconds between two bytes that the latter is considered to be part of a new package. The default is 100 miliseconds. Use this option in conjunction with the \-\-timing\-print option. .TP \fB\-g\fR, \fB\-\-timing\-print\fR Print a line of timing information before every continues stream of bytes. When multiple serial devices are given also print the name or alias of the device where the data is coming from. .TP \fB\-i\fR, \fB\-\-width\fR=\fIWIDTH\fR The number of bytes to display on one line. The default is 16. .PP Write options: .TP \fB\-c\fR, \fB\-\-checksum\fR Append a single checksum byte to the line of data written to the serial device(s) chosen. This checksum is a simple modulo 256 addition of all input bytes on a line. .TP \fB\-z\fR, \fB\-\-crc8\fR=\fIPOLY\fR Append a crc8 checksum to the line of data written to the serial device(s) chosen. Use the optionally given poly as the polynomial. Specify the polynomial as hexadecimal value, as in 0x07 (the default). .TP \fB\-y\fR, \fB\-\-crc16\fR=\fIPOLY\fR Append a crc16 checksum to the line of data written to the serial device(s) chosen. Use the optionally given poly as the polynomial. Specify the polynomial as hexadecimal value, as in 0xA001 (the default). .TP \fB\-k\fR, \fB\-\-delay\-byte\fR=\fIMICROSECONDS\fR This delay is an optional amount of microseconds to wait in between every input byte is sent on the serial device(s). .TP \fB\-d\fR, \fB\-\-delay\-line\fR=\fIMICROSECONDS\fR This delay is an optional amount of microseconds to wait in between every input line is sent on the serial device(s). .TP \fB\-j\fR, \fB\-\-fuck\-up\fR This is the special fuck up option. When the calculation of a checksum is chosen (see checksum and crc* options) the checkum will be crippled on purpose. Carefully named after the special Jan Arie de Bruin 'fuck up crc' button. .TP \fB\-n\fR, \fB\-\-no\-send\fR Do not actually send the bytes on the serial device(s). Rather pointless, but seemed one day long ago to be a rather handy feature. .TP \fB\-p\fR, \fB\-\-print\fR Besided sending the data on the serial device(s) also write the data to stdout. .TP \fB\-s\fR, \fB\-\-size\fR=\fISIZE\fR The maximum number of bytes per line to send on the serial device(s). The default is 22, coming from back in the Cham2 days of the program. .SH DIAGNOSTICS Normally, exit status is 0 if the program did run with no problem whatsoever. If the exit status is not equal to 0 an error message is printed on stderr which should help you solve the problem. .SH BUGS .PP \fBOrder of bytes broke when reading several tty devices at once\fR .PP The display of incoming bytes can be broke if you use multiple tty devices to read from. At the moment I do not have a solution for this problem. Since I use select() to watch the several tty devices and after the select() I have to read() them one by one, I can not completely 100% display which bytes came after which on different tty devices. Take the example below: .PP .RS .nf .sp .5 $ jpnevulator \-\-ascii \-\-timing\-print \-\-tty /dev/ttyS0 \-\-tty /dev/ttyUSB0 \-\-read 2006-05-30 13:23:49.461075: /dev/ttyS0 00 00 05 3B 0D 00 00 05 ...;.... 2006-05-30 13:23:49.461113: /dev/ttyUSB0 00 05 3B 0D 00 00 05 3B 0D ..;....;. 2006-05-30 13:23:49.473074: /dev/ttyS0 3B 0D 00 00 05 3B 0D ;....;. 2006-05-30 13:23:49.473105: /dev/ttyUSB0 00 12 05 06 39 00 12 05 06 39 1F 00 22 80 00 0E ....9....9.."... $ .sp .5 .fi .RE .PP And now see the order in which things really got sent on the line: .PP .RS .nf .sp .5 /dev/ttyS0: 00 00 05 3B 0D /dev/ttyUSB0: 00 00 05 3B 0D /dev/ttyS0: 00 00 05 3B 0D /dev/ttyUSB0: 00 00 05 3B 0D /dev/ttyS0: 00 00 05 3B 0D /dev/ttyUSB0: 00 00 05 3B 0D 00 12 05 06 39 00 12 05 06 39 ... .sp .5 .fi .RE .PP As you can see /dev/ttyUSB0 receives the echo of all things sent by /dev/ttyS0. This is exactly what happens. But since there does exist a small time between the select() who is happy expressing something is available and the read() who does get the available data, some extra data will be available. I have no idea on how I can use high level system call like select() and read() and be still able to put the bytes in the correct order. Anyone an idea? .SH AUTHOR Written by Freddy Spierenburg. .SH "REPORTING BUGS" Report bugs to . .SH COPYRIGHT Copyright \(co 2006-2012 Freddy Spierenburg jpnevulator-2.1.1/tty.h0000644000214200000620000000157311714040760014214 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __TTY_H #define __TTY_H extern enum interfaceRtrn ttyAdd(char *); #endif jpnevulator-2.1.1/list.c0000644000214200000620000002613112007305573014341 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "list.h" /* This routine initializes our list meta data. */ enum listRtrn listInitialize(list_t *list) { list->first=list->last=list->current=NULL; list->elements=0; return(listRtrnOk); } /* This routine appends one element to the list. It will * be appended just after the current element. */ enum listRtrn listAppend(list_t *list,void *data) { struct listElement *p; /* Allocate memory for the new element. */ p=(struct listElement *)malloc(sizeof(p[0])); if(p!=NULL) { /* Assign the data to the element. */ p->data=data; /* Do any elements exist already in the list? */ if(list->current!=NULL) { /* Yes, we will append this one after the current one. */ /* Is the current one the last one in the list? */ if(list->current->next!=NULL) { /* No, so we have to let the one after the current know * that we will be the previous element from now on. */ list->current->next->previous=p; } else { /* Yes, so we tell the meta data that we are the last in the * list right now. */ list->last=p; } /* Our next one will be the next one of the current element. */ p->next=list->current->next; /* Our previous one will be the current element. */ p->previous=list->current; /* And of course we should let the current element know that * we come next in the list. */ list->current->next=p; } else { /* No, there do not exist any elements in the list yet so we * are the first, last and current. */ p->previous=p->next=NULL; list->first=list->last=list->current=p; } /* Increase the amount of elements known to the list. */ list->elements++; return(listRtrnOk); } else { return(listRtrnMemory); } } /* This routine insert one element to the list. It will * be inserted just before the current element. */ enum listRtrn listInsert(list_t *list,void *data) { struct listElement *p; /* Allocate memory for the new element. */ p=(struct listElement *)malloc(sizeof(p[0])); if(p!=NULL) { /* Assign the data to the element. */ p->data=data; /* Do any elements exist already in the list? */ if(list->current!=NULL) { /* Yes, we will insert this one before the current one. */ /* Our previous one will be the one before the current element. */ p->previous=list->current->previous; /* We will be the previous one for the current element. */ list->current->previous=p; /* Our next one will be the current element. */ p->next=list->current; /* Are we now the first one in the list? */ if(p->previous!=NULL) { /* No, so we have to let the one before us know that we * will be the next element from now on. */ p->previous->next=p; } else { /* Yes, so we tell the meta data that we are the first in the * list right now. */ list->first=p; } } else { /* No, there do not exist any elements in the list yet so we * are the first, last and current. */ p->previous=p->next=NULL; list->first=list->last=list->current=p; } /* Increase the amount of elements known to the list. */ list->elements++; return(listRtrnOk); } else { return(listRtrnMemory); } } /* This routine removes the current element from the list. If none available * it does nothing. */ void listRemove(list_t *list,void (*garbageCollect)(void *)) { /* Any elements in the list available? */ if(list->current!=NULL) { struct listElement *p; /* Yes, let's remove the current one. */ p=list->current; /* Is it the first element in the list? */ if(p->previous!=NULL) { /* No, so let the element before know what the new element after * it will be. */ list->current->previous->next=p->next; } else { /* Yes, so update the first meta data. */ list->first=p->next; } /* Is it the last element in the list? */ if(p->next!=NULL) { /* No, so let the element after it know what the new element * before it will be. */ p->next->previous=p->previous; } else { /* Yes, so update the last meta data. */ list->last=p->previous; } /* Now we need to update the current meta data. Does an element * after this element exist? */ if(p->next!=NULL) { /* Yes, this next element will be the new current element. */ list->current=p->next; } else { /* No, the element before this one will be the new current element. */ list->current=p->previous; } /* Run the garbage collector for this item if required. */ if(garbageCollect!=NULL) { garbageCollect(p->data); } /* Return system resources. */ free(p); /* Decrease the amount of elements known to the list. */ list->elements--; } } /* This routine returns the data of the current element or NULL if * none is available. */ void *listCurrent(list_t *list) { return(list->current!=NULL?list->current->data:NULL); } /* This routine returns the first element in the list or NULL if * none is available. It also sets the current meta data to be the * first element in the list. */ void *listFirst(list_t *list) { list->current=list->first; return(listCurrent(list)); } /* This routine returns the next element in the list or NULL if * none is available. It also advances the current meta data to the * next element. */ void *listNext(list_t *list) { if((list->current!=NULL)&&(list->current->next!=NULL)) { list->current=list->current->next; return(listCurrent(list)); } else { return(NULL); } } /* This routine returns the previous element in the list or NULL if * none is available. It also sets the current meta data to the * previous element. */ void *listPrevious(list_t *list) { if((list->current!=NULL)&&(list->current->previous!=NULL)) { list->current=list->current->previous; return(listCurrent(list)); } else { return(NULL); } } /* This routine returns the last element in the list or NULL if * none is available. It also sets the current meta data to be the * last element in the list. */ void *listLast(list_t *list) { list->current=list->last; return(listCurrent(list)); } /* This routine search the list for a specific element given by needle and * returns that element or NULL if it's not found. */ void *listSearch(list_t *list,int (*compare)(void *,void *),void *needle) { void *data; int found; /* At first we of course didn't find anything and especially when we do not receive a list we make sure we did not found anything as of yet. */ found=0; /* Does any element exist in the list? */ if((data=listFirst(list))!=NULL) { do { /* Yes, so search for our element... */ if((found=compare(data,needle))) break; /* ...untill none left. */ } while((data=listNext(list))!=NULL); } /* If we found our data return it, otherwise return NULL. */ return(found?data:NULL); } /* This routine gracefully returns all system resources and empty the * list. */ void listDestroy(list_t *list,void (*garbageCollect)(void *)) { struct listElement *p; /* Search untill no elements are left... */ while(list->first!=NULL) { /* First save a reference to our next element. */ p=list->first->next; /* Run the garbage collector for this item if required. */ if(garbageCollect!=NULL) { garbageCollect(list->first->data); } /* Then return resources for the current one. */ free(list->first); /* And at last advance to our next element. */ list->first=p; } /* Reset all our meta data. */ list->first=list->last=list->current=NULL; list->elements=0; } #if 0 #include #include #include #include int cmpr(void *p,void *q) { return(!strcmp((char *)p,(char *)q)); } void garbageCollect(void *data) { printf("Taking down: %s\n",(char *)data); } int main(int argc,char **argv) { list_t list; int index; char *arg; int elements; /* Initialize our list. */ listInitialize(&list); /* Fill our list with all command line arguments given, but skip the * first argument since that's our needle (see below -> listSearch()). */ for(index=2;index=2) { /* ...search for the first one given... */ arg=listSearch(&list,cmpr,(void *)argv[1]); /* ...and tell if it's found. */ printf("searching for [%s]... %sfound\n",argv[1],arg!=NULL?"":"not "); } /* Randomly remove half of the arguments. */ srandom(getpid()); for(elements=listElements(&list)/2;elements>0;elements--) { int element=(random()%(argc-2))+2; arg=listSearch(&list,cmpr,(void *)argv[element]); printf("Removing [%s]... ",argv[element]); if(arg!=NULL) { listRemove(&list,NULL); printf("ok\n"); } else { printf("not in the list!\n"); } } /* Print all our arguments from the first to the last. */ printf("First to last:\n"); /* Does any argument exist? */ if((arg=(char *)listFirst(&list))!=NULL) { /* Yes, we print it and... */ do { printf("[%s]\n",arg); /* ...advance to the next argument, untill none left. */ } while((arg=(char *)listNext(&list))!=NULL); } else { printf("empty list\n"); } /* Print all our arguments from the last to the first. */ printf("Last to first:\n"); /* Does any argument exist? */ if((arg=(char *)listLast(&list))!=NULL) { /* Yes, we print it and... */ do { printf("[%s]\n",arg); /* ...advance to the next argument, untill none left. */ } while((arg=(char *)listPrevious(&list))!=NULL); } else { printf("empty list\n"); } /* Destroy the list and all its elements. */ listDestroy(&list,garbageCollect); return(0); } #endif jpnevulator-2.1.1/INSTALL0000644000214200000620000000126111173653137014255 0ustar freddystaffINSTALL ======= This file contains information on how to build and install jpnevulator on your computer. For run-time information, check the README file and the manual page. See the homepage for jpnevulator http://jpnevulator.snarl.nl/ for more information. Download ======== The latest version of the software is available from http://jpnevulator.snarl.nl/. At this moment there do not exist any pre-compiled binaries. Building jpnevulator is so easy that anybody interested in the program should be able to do it. Compiling ========= $ make After this make you will have a binary called jpnevulator in the main source directory. You can copy this binary everywhere you like. jpnevulator-2.1.1/debian/0000755000214200000620000000000012010014413014421 5ustar freddystaffjpnevulator-2.1.1/debian/source/0000755000214200000620000000000011706652611015744 5ustar freddystaffjpnevulator-2.1.1/debian/source/format0000644000214200000620000000001411706652611017152 0ustar freddystaff3.0 (quilt) jpnevulator-2.1.1/debian/control0000644000214200000620000000156611706650231016053 0ustar freddystaffSource: jpnevulator Homepage: http://jpnevulator.snarl.nl/ Section: comm Priority: optional Maintainer: Freddy Spierenburg Build-Depends: debhelper (>= 5) Standards-Version: 3.9.2 Package: jpnevulator Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Serial sniffer jpnevulator is a handy serial sniffer. You can use it to send data on a serial device too. You can read or write from/to one or more serial devices at the same time. . In write mode data to be sent on the serial device(s) is read from a file or stdin in hexadecimal notation. Data is sent on the serial device(s) line by line. . In read mode data to be read from the serial device(s) is written to a file or stdout in hexadecimal notation. It's even possible to pass the data in between the serial device(s). Several options enhance the way the data is displayed. jpnevulator-2.1.1/debian/compat0000644000214200000620000000000210440307734015637 0ustar freddystaff5 jpnevulator-2.1.1/debian/docs0000644000214200000620000000002511706660161015313 0ustar freddystaffBUGS README TODO FAQ jpnevulator-2.1.1/debian/copyright0000644000214200000620000000121011706647527016403 0ustar freddystaffThis package was debianized by Freddy Spierenburg on Sat, 3 Jun 2006 15:34:17 +0200. It was downloaded from http://jpnevulator.snarl.nl/ Upstream Author: Freddy Spierenburg This software is Copyright 2006-2012 by Freddy Spierenburg. You are free to distribute this software under the terms of the GNU General Public License. On Debian systems, the complete text of the GNU General Public License can be found in the file `/usr/share/common-licenses/GPL'. The Debian packaging is Copyright 2006-2012, Freddy Spierenburg and is licensed under the GPL, see `/usr/share/common-licenses/GPL'. jpnevulator-2.1.1/debian/watch0000644000214200000620000000010411706645704015475 0ustar freddystaffversion=3 http://jpnevulator.snarl.nl/download/jpnevulator-(.+).tgz jpnevulator-2.1.1/debian/rules0000755000214200000620000000420612007310365015516 0ustar freddystaff#!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 CFLAGS:=$(shell dpkg-buildflags --get CFLAGS) -Wall CPPFLAGS:=$(shell dpkg-buildflags --get CPPFLAGS) LDFLAGS:=$(shell dpkg-buildflags --get LDFLAGS) ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) CFLAGS += -O0 else CFLAGS += -O2 endif configure: configure-stamp configure-stamp: dh_testdir # Add here commands to configure the package. touch configure-stamp build: build-arch build-indep build-arch: build-stamp build-indep: build-stamp build-stamp: configure-stamp dh_testdir # Add here commands to compile the package. $(MAKE) CFLAGS="$(CFLAGS)" CPPFLAGS="$(CPPFLAGS)" LDFLAGS="$(LDFLAGS)" #docbook-to-man debian/jpnevulator.sgml > jpnevulator.1 touch $@ clean: dh_testdir dh_testroot rm -f build-stamp configure-stamp # Add here commands to clean up after the build process. $(MAKE) clean dh_clean install: build dh_testdir dh_testroot dh_prep dh_installdirs # Add here commands to install the package into debian/jpnevulator. $(MAKE) install DESTDIR=$(CURDIR)/debian/jpnevulator # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install dh_testdir dh_testroot dh_installchangelogs Changelog dh_installdocs dh_installexamples # dh_install # dh_installmenu # dh_installdebconf # dh_installlogrotate # dh_installemacsen # dh_installpam # dh_installmime # dh_python # dh_installinit # dh_installcron # dh_installinfo dh_installman dh_link dh_strip dh_compress dh_fixperms # dh_perl # dh_makeshlibs dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install configure jpnevulator-2.1.1/debian/changelog0000644000214200000620000000354212010014413016277 0ustar freddystaffjpnevulator (2.1.1-1) unstable; urgency=low * New release. -- Freddy Spierenburg Mon, 06 Aug 2012 21:20:35 +0200 jpnevulator (2.1.0-1) unstable; urgency=low * New release. -- Freddy Spierenburg Sun, 05 Aug 2012 22:47:38 +0200 jpnevulator (2.0.3-1) unstable; urgency=low * New release. -- Freddy Spierenburg Wed, 09 May 2012 21:25:05 +0200 jpnevulator (2.0.2-1) unstable; urgency=low * New release. -- Freddy Spierenburg Tue, 17 Apr 2012 18:51:18 +0200 jpnevulator (2.0.1-1) unstable; urgency=low * New release. -- Freddy Spierenburg Mon, 16 Apr 2012 18:25:08 +0200 jpnevulator (2.0.0-1) unstable; urgency=low * New release. -- Freddy Spierenburg Sun, 15 Apr 2012 23:26:33 +0200 jpnevulator (1.3.1-1) unstable; urgency=low * New release. -- Freddy Spierenburg Sun, 22 Jan 2012 00:14:01 +0100 jpnevulator (1.3.0-1) unstable; urgency=low * New release. -- Freddy Spierenburg Sat, 25 Apr 2009 13:00:53 +0200 jpnevulator (1.2.3-1) unstable; urgency=low * New upstream release. * First official upload to Debian, closes bug#378671. -- Freddy Spierenburg Fri, 21 Jul 2006 15:17:27 +0200 jpnevulator (1.2.2-1) unstable; urgency=low * New upstream release. -- Freddy Spierenburg Mon, 17 Jul 2006 00:20:47 +0200 jpnevulator (1.2.1-1) unstable; urgency=low * New upstream release. -- Freddy Spierenburg Sun, 25 Jun 2006 16:08:19 +0200 jpnevulator (1.2.0-1) unstable; urgency=low * New upstream version. -- Freddy Spierenburg Sun, 25 Jun 2006 14:10:55 +0200 jpnevulator (1.1.0-1) unstable; urgency=low * Initial release. -- Freddy Spierenburg Sat, 3 Jun 2006 15:34:17 +0200 jpnevulator-2.1.1/byte.h0000644000214200000620000000166511706642645014354 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __BYTE_H #define __BYTE_H enum byteRtrn { byteRtrnEOF=-128, byteRtrnEOL, byteRtrnUnknown }; extern int byteGet(FILE *); #endif jpnevulator-2.1.1/jpnevulator.h0000644000214200000620000000244012010012370015721 0ustar freddystaff#ifndef __JPNEVULATOR_H /* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #define __JPNEVULATOR_H #include "options.h" #define PROGRAM_NAME "jpnevulator" #define PROGRAM_VERSION "2.1.1" enum jpnevulatorRtrn { jpnevulatorRtrnOk=0, jpnevulatorRtrnOptions, jpnevulatorRtrnNoTTY, jpnevulatorRtrnNoInput, jpnevulatorRtrnNoOutput, jpnevulatorRtrnNoMessage, jpnevulatorRtrnNoAscii }; extern struct jpnevulatorOptions _jpnevulatorOptions; extern enum jpnevulatorRtrn jpnevulatorWrite(void); extern enum jpnevulatorRtrn jpnevulatorRead(void); #endif jpnevulator-2.1.1/interface.h0000644000214200000620000000304011742603154015326 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __INTERFACE_H #define __INTERFACE_H struct interface { char name[32]; char alias[32]; int fd; unsigned long byteCount; int control; void (*close)(int); int (*controlGet)(int,char *); void (*controlWrite)(FILE *,int); }; enum interfaceRtrn { interfaceRtrnOk=0, interfaceRtrnDouble, interfaceRtrnMemory, interfaceRtrnOpen, interfaceRtrnList }; #define interfacePrint(x) (strlen((x)->alias)>0?(x)->alias:(x)->name) extern void interfaceInitialize(void); extern enum interfaceRtrn interfaceAdd(char *,int (*)(char *,int),int (*)(int,char *),void (*)(FILE *,int),void (*)(int)); extern int interfaceControlGet(struct interface *); extern void interfaceControlWrite(struct interface *,FILE *,int); extern void interfaceDestroy(void); #endif jpnevulator-2.1.1/TODO0000644000214200000620000000151611706641005013710 0ustar freddystaffTODO ==== This is the TODO file. Some of these things will eventually happen too. :-) Hey, it appears that all of them are done at this particular point in time. DONE ==== 2006-05-30: 0 (2006-06-02) Create --index option. This way some sort of index numbers will appear in front of all the read bytes. Might be handy with referencing. The option is named --byte-count instead of --index. 2006-05-30: 2 (2006-06-03) Write a decent manual page. 2006-05-30: 5 (2006-05-30) Release the whole software. 2006-05-30: 4 (2006-05-30) Setup a nice website and mailing list. Waited with a mailing list untill some users demand it. 2006-05-30: 1 (2006-06-03) Add --byte-delay option. This creates a delay between the sending of each byte in a line. Idea courtesy of Michiel van Dam. 2006-05-30: 3 (2006-06-06) Create a Debian package. jpnevulator-2.1.1/crc8.h0000644000214200000620000000170011706642725014235 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CRC8_H #define __CRC8_H extern void crc8PolyInit(unsigned char); extern unsigned char crc8Calculate(unsigned char *,unsigned short); #endif jpnevulator-2.1.1/README0000644000214200000620000001123712007556416014107 0ustar freddystaffREADME ====== This is jpnevulator. What once started as a Jackpot Navigator emulator (hence the strange name) is now a nice serial sniffer and you can use it to send data on a serial line too. It's sort of like a very simple terminal emulator, like picocom. But jpnevulator uses hexadecimal byte values to display and send along the line. Very handy indeed if you are working a lot with serial protocols. Please see the INSTALL file on how to build the program. It's so easy, anyone should be able to do it. Just make sure you have a compiler on your computer. You are running a Free Operating System aren't you? Of course you are! :-) If you need any more information on how to use the program, please read the fine manual. Have fun! As a last note. I once did read a README file or the like from a program, if I'm correct it was xdm. The author asked for anyone who used and liked his program to send him a postcard from the area where they live in. Of course I did and besides that liked the idea very much. So as a shameless act of copying I'm asking from you to do the same. If you like the program I would really love to hear from you by means of a postcard. You can send it to: Freddy Spierenburg Veluwemeer 206 3446 JD Woerden The Netherlands Thanks in advance and again; have fun using this program! Thank you ========= Thanks to Michiel van Dam for some good additional ideas. I also like to thank Dr. Octagon and Colonel Claypool for inspiring music while coding. Thanks to Ardor for his question which inspired a new great idea! Shame on me I did not came up with it myself in the first place. :) Thanks to Paul Slootman for making it possible this software is part of Debian. Thanks to Eric Shattow for his idea to use pseudo-terminal devices. Thanks to Gustavo Conrad for his feature request to monitor the serial port control lines. Thanks to his question I decided to write the code to enable it. Thanks to Duane A. Damiano for his feature request to stop reading after a provided amount of bytes. Enhanced the request into stopping reading and writing where appropriate. History ======= The first version of jpnevulator was written around the summer of 2004, when I worked as a software engineer for Gaming Support. At the time I was working on Jackpot Junction, a visual jackpot celebration program. For testing purposes I needed some jackpot values that would automatically change in time, like our Jackpot Navigator did when coins would get played on gaming machines. I would then feed those values by means of a serial cable to the Jackpot Junction system. The first version of jpnevulator was born! It had like six different jackpot values it would randomly increase and all those values where sent to the Jackpot Junction by means of the Cham2 protocol. Here the default message size of 22 stems from. :-) Soon I needed a more flexible system in which I could alter bytes in any way I wanted, because there where more protocols to send. That's when the second version of the program came into shape, sort of like the --write option is working nowadays. It would read bytes from stdin or a file and would write them to a serial interface. I used this version of jpnevulator a lot of times and was very happy with it. Then I started working for D.A.R.E!! in the start of 2006. For some serious debugging of the MIPS Linux kernel serial drivers for the AMD Alchemy AU1100 board I needed something in which I knew exactly what was sent on the serial line and what was not. I also needed something to read those bytes again. The --read option was born and worked wonderfully well. Not long after I invented the --read option I added support for the timing information. It was around then that I notices that jpnevulator was no longer a jackpot navigator emulator, but more a serial sniffer. And that it could be useful to other people. So that's why I released the software as Free Software. Let's see what happens to it... Copyright notice ================ Copyright (C) 2006-2012 Freddy Spierenburg 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Freddy Spierenburg jpnevulator-2.1.1/FAQ0000644000214200000620000000273011742636351013561 0ustar freddystaffFAQ === This is actually a quiet lousy FAQ with only one question answered. But the truth is that only one question is asked frequently. Q: Your serial tool seems to block my application. What am I doing wrong? A: First the bad news: It's impossible for two GNU/Linux processes to open the same serial port at the same time. Doing so results in undefined behaviour like you just experienced. Jpnevulator was never built to sit in between the kernel and your application. I'm sorry. The way I have used Jpnevulator over and over again, was with a special self (not entirely myself, but a colleague of mine) made device that sort of sits in between a serial cable. Out of the device comes another serial cable that mirrors everything that is sent over the original serial cable. A sort of man in the middle. Now with a little bit of luck some good news: A little while ago Eric Shattow suggested to use pseudo-terminal devices to sit in between the kernel and your application. Unfortunately it's still impossible to work with speed changes that way and hence Eric never replied when I asked him what he did think of the solution I provided to him. So this pseudo-terminal device support is not tested very well, only in a limited way by me. It works and I think it's even relatively easy to use stty to detect speed changes and act upon it. I leave that as an exercise to the reader, but I would love to hear from anyone having done it. jpnevulator-2.1.1/Makefile0000644000214200000620000000474412007311104014653 0ustar freddystaff# jpnevulator - serial reader/writer # Copyright (C) 2006-2012 Freddy Spierenburg # # 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 2 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, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Name of the binary. NAME=jpnevulator # Destination where to put our stuff 'make install'. ifeq ($(origin DESTDIR), undefined) bindir=/usr/local/bin mandir=/usr/local/man/man1 else bindir=$(DESTDIR)/usr/bin mandir=$(DESTDIR)/usr/share/man/man1 endif # List of the objects to built. OBJECTS=main.o OBJECTS+=options.o OBJECTS+=jpnevulator.o OBJECTS+=byte.o OBJECTS+=interface.o OBJECTS+=tty.o OBJECTS+=pty.o OBJECTS+=io.o OBJECTS+=checksum.o OBJECTS+=crc16.o OBJECTS+=crc8.o OBJECTS+=list.o # List of the manual pages. MANPAGES=jpnevulator.1.gz # Tools CLIBS= CFLAGS=-Wall LDFLAGS= CC=gcc GZIP=gzip INSTALL=install .PHONY: all FORCE clean install all: $(NAME) $(MANPAGES) $(NAME): $(OBJECTS) $(CC) $(CFLAGS) $(LDFLAGS) -o $(NAME) $(CLIBS) $(OBJECTS) $(MANPAGES): $(GZIP) --best -c `echo $@|sed 's/\.gz$$//'` > $@ clean: rm -f $(NAME) $(OBJECTS) $(MANPAGES) install: $(NAME) $(MANPAGES) $(INSTALL) -D -m 0755 $(NAME) $(bindir)/$(NAME) for manual in $(MANPAGES); do \ $(INSTALL) -D -m 0644 $$manual $(mandir)/$$manual; \ done # Dummy target as dependecy if something has to be build everytime FORCE: # Automatic collection of dependencies in the source files. # It's only updated the first time, after that it must be done maually # with "make depend" # Target to update the file, it's removed first dependall: dependrm depend #remove the file dependrm: rm -f dependencies.in # Build the file that contains the dependencies. No deps in this rule. # If there were deps it would be rebuilt every chnage, which is unneeded: depend: dependencies.in @echo "depend" dependencies.in: $(CC) -MM $(CFLAGS) $(patsubst %.o,%.c,$(OBJECTS)) >$@ # The dependecies are included from a separate file: -include dependencies.in jpnevulator-2.1.1/AUTHORS0000644000214200000620000000021110433626507014265 0ustar freddystaffAUTHORS - who wrote what on jpnevulator? ======================================== * Freddy Spierenburg Main author jpnevulator-2.1.1/io.c0000644000214200000620000000241511706642766014011 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include "io.h" #include "options.h" #include "jpnevulator.h" #define ioIsStdio() ((strcmp(_jpnevulatorOptions.io,ioMAGIC)==0)||strcmp(_jpnevulatorOptions.io,"-")==0) FILE *ioOpen(char *mode) { if(ioIsStdio()) { FILE *ioHandle; if(strstr(mode,"r")!=NULL) { ioHandle=stdin; } else { ioHandle=stdout; } return(ioHandle); } else { return(fopen(_jpnevulatorOptions.io,mode)); } } void ioClose(FILE *fd) { if(!ioIsStdio()) { fclose(fd); } } jpnevulator-2.1.1/checksum.c0000644000214200000620000000176711706642707015210 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ unsigned short checksumCalculate(unsigned char *data,unsigned short length) { unsigned short checksum,index; for(index=0,checksum=0;index Copyright (C) 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 2 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. jpnevulator-2.1.1/tty.c0000644000214200000620000000404611742634252014213 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include #include #include #include #include "jpnevulator.h" #include "interface.h" #include "tty.h" static int ttyOpen(char *name,int length) { int fd; struct termios options; fd=open(name,O_RDWR); if(fd!=-1) { /* Make sure we send to a raw serial interface! */ fcntl(fd,F_SETFL,0); tcgetattr(fd,&options); cfmakeraw(&options); tcsetattr(fd,TCSANOW,&options); } return(fd); } static int ttyControlGet(int fd,char *name) { int control; control=0; if(ioctl(fd,TIOCMGET,&control)) { char error[256]; sprintf(error,"%s: Can't get the modem control bits of interface %s",PROGRAM_NAME,name); perror(error); } return control; } static void ttyControlWrite(FILE *output,int control) { fprintf( output, "le=%d, dtr=%d, rts=%d, st=%d, sr=%d, cts=%d, cd=%d, ri=%d, dsr=%d\n", control&TIOCM_LE?1:0, control&TIOCM_DTR?1:0, control&TIOCM_RTS?1:0, control&TIOCM_ST?1:0, control&TIOCM_SR?1:0, control&TIOCM_CTS?1:0, control&TIOCM_CD?1:0, control&TIOCM_RI?1:0, control&TIOCM_DSR?1:0 ); } static void ttyClose(int fd) { close(fd); } enum interfaceRtrn ttyAdd(char *name) { return(interfaceAdd(name,ttyOpen,ttyControlGet,ttyControlWrite,ttyClose)); } jpnevulator-2.1.1/checksum.h0000644000214200000620000000164411706642713015204 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __CHECKSUM_H #define __CHECKSUM_H extern unsigned short checksumCalculate(unsigned char *,unsigned short); #endif jpnevulator-2.1.1/list.h0000644000214200000620000000402211706643022014340 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __LIST_H #define __LIST_H enum listRtrn { listRtrnOk=0, listRtrnMemory }; struct listElement { void *data; struct listElement *previous; struct listElement *next; }; typedef struct list { struct listElement *first; struct listElement *last; struct listElement *current; int elements; } list_t; /* Do notice the use of -> in listElements, so it conforms to all the * other routines in that you need to give the address of the list. */ #define listElements(x) ((x)->elements) extern enum listRtrn listInitialize(list_t *); extern enum listRtrn listAppend(list_t *,void *); extern enum listRtrn listInsert(list_t *,void *); extern void listRemove(list_t *,void (*)(void *)); extern void *listCurrent(list_t *); /* These next two are routines to temporary freeze the current pointer in the list. This * way one can traverse the list within a traverse of the list itself. */ #define listCurrentPositionSave(x) ((x)->current) #define listCurrentPositionLoad(x,y) ((x)->current=y) extern void *listFirst(list_t *); extern void *listNext(list_t *); extern void *listPrevious(list_t *); extern void *listLast(list_t *); extern void *listSearch(list_t *,int (*)(void *,void *),void *); extern void listDestroy(list_t *,void (*)(void *)); #endif jpnevulator-2.1.1/misc.h0000644000214200000620000000215311742553551014332 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef __MISC_H #define __MISC_H #define max(x,y) ((x)>(y)?(x):(y)) #define min(x,y) ((x)<(y)?(x):(y)) typedef char bool_t; #define boolTrue 1 #define boolFalse 0 #define boolSet(x) ((x)=boolTrue) #define boolReset(x) ((x)=boolFalse) #define boolIsSet(x) ((x)==boolTrue) #define boolIsNotSet(x) ((x)==boolFalse) #endif jpnevulator-2.1.1/main.c0000644000214200000620000000256311713526317014321 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "jpnevulator.h" #include "options.h" int main(int argc,char **argv) { int returnValue; if(optionsParse(argc,argv)!=optionsRtrnOk) { returnValue=jpnevulatorRtrnOptions; } else { switch(_jpnevulatorOptions.action) { case actionTypeRead: { returnValue=jpnevulatorRead(); break; } case actionTypeWrite: { returnValue=jpnevulatorWrite(); break; } case actionTypeNone: default: { /* Should be impossible. :-) */ returnValue=optionsRtrnImpossible; break; } } } return(returnValue); } jpnevulator-2.1.1/crc16.c0000644000214200000620000000313311706642715014310 0ustar freddystaff/* jpnevulator - serial reader/writer * Copyright (C) 2006-2012 Freddy Spierenburg * * 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 2 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, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ static unsigned short crcTable[256]; static unsigned short calcCRC(unsigned short seed,unsigned short poly,unsigned short data) { unsigned short index; unsigned short crc=seed; for(index=8;index;index--) { if((data^crc)&0x0001) { crc=(crc>>1)^poly; } else { crc>>=1; } data>>=1; } return(crc); } void crc16TableCreate(unsigned short seed,unsigned short poly) { unsigned short index; for(index=0;index<256;index++) { crcTable[index]=calcCRC(seed,poly,index); } } static unsigned short crcAdd(unsigned short crc,unsigned char byte) { return(crc>>8)^crcTable[(crc&0xFF)^byte]; } unsigned short crc16Calculate(unsigned char *data,unsigned short length) { unsigned short crc; unsigned short index; crc=0; for(index=0;index #define ioMAGIC "xi2aeniJeeHoo4wuohQuu7ioiev5eiJe" extern FILE *ioOpen(char *); extern void ioClose(FILE *); #endif