/*==============================================================================*/ /* CAN232 data logger */ /* */ /* This program records the incoming data from the CAN232 and stores in files. */ /* It uses a double buffer mechanism, while recording is done to one of the */ /* buffers, saving is done from the other. The 2 processes communicate via */ /* signals and exhange data from shared memory. */ /* The file name is generated based on seqnum/date/time. */ /* On top of logging the data from the CAN232, it inserts timestamps every */ /* second with 0xFFE id. ( tFFE0:%06d ) and characters pressed with id 0xFFF */ /* ( tFFF0:%02x ). These are useful when analyzing the traffic. */ /* */ /* DATE: 2004-May-19 17:52:27 */ /* */ /* Copyright (c) 2004 Attila Vass */ /* */ /* Permission is hereby granted, free of charge, to any person obtaining a copy */ /* of this software and associated documentation files (the "Software"),to deal */ /* in the Software without restriction, including without limitation the rights */ /* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ /* copies of the Software, and to permit persons to whom the Software is */ /* furnished to do so, subject to the following conditions: */ /* */ /* The above copyright notice and this permission notice shall be included in */ /* all copies or substantial portions of the Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ /* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ /* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ /* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ /* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS */ /* IN THE SOFTWARE. */ /*==============================================================================*/ /* gcc canpoll.c -o canpoll */ #include #include #include #include #include #include #include #include #include #include #include #include #include //#define COMM_DEBUG 1 //#define COLL_DEBUG 1 #define WORK_MEMORY_SIZE (32*1024*1024) // Up to 64 Meg each, since I have 512M available, 370M most of the time #define COMM_MEMORY_SIZE 256 #define NEWLINE_CHAR 0x0D #define BAUD B230400 #define DEVICE "/dev/ttyUSB0" long zeso=0; long curtime=0; unsigned char Maingo=1,SamplingIsStopped=0; int SharedDataMemId[2]; // for Dual Buffer char* SharedDataMemPtr[2]; // for Dual Buffer int SharedCommMemId; char* SharedCommMemPtr; char Message[32]; unsigned int ActiveBank=0,AB_Cntr=0,ActiveFile=0,DiskIO=0; struct shmid_ds SMMyInfo; static pid_t PidMain=-1,PidCollector=-1,PidMine=-1; int Port=-1; time_t StartTime=0; void gettime(void) { struct timeval ltim; gettimeofday(<im,NULL); curtime=((ltim.tv_sec-zeso)*1000)+(ltim.tv_usec/1000); } void zerotime(void) // This could take up to a second... { struct timeval ltim; register int a; register long b=0; while(1) { gettimeofday(<im,NULL); if(ltim.tv_usec=(WORK_MEMORY_SIZE-10)) // Chg Bank, signal chg... { SharedCommMemPtr[1]=ActiveBank; SharedCommMemPtr[2]='N'; if(++ActiveBank>1) ActiveBank=0; *((unsigned int *)(SharedCommMemPtr+16))=AB_Cntr; kill(PidMain,SIGUSR1); AB_Cntr=0; } #else int a; if(SamplingIsStopped) { return(0); } #if 1 if((rand()&0x40)!=0x40) return; ret=rand()&0x1F; if(ret=>(WORK_MEMORY_SIZE-AB_Cntr+1)) ret=(WORK_MEMORY_SIZE-AB_Cntr-2); for(a=0;a=(WORK_MEMORY_SIZE-10)) // Chg Bank, signal chg... { SharedCommMemPtr[1]=ActiveBank; SharedCommMemPtr[2]='N'; if(++ActiveBank>1) ActiveBank=0; *((unsigned int *)(SharedCommMemPtr+16))=AB_Cntr; kill(PidMain,SIGUSR1); AB_Cntr=0; } #endif return(ret); } void InsertTimeStamp(void) { char* PB=SharedDataMemPtr[ActiveBank]; char Message[32]; int a,b,c,d; gettime(); #ifdef COMM_DEBUG printf("\ntimestamp : %06d",curtime);fflush(stdout); #endif sprintf(Message,"tFFE0:%06d%c\0",curtime,NEWLINE_CHAR); // My ID of 0xFFE with 0 byte indicator, but :%d is timestamp for(a=0;Message[a]!='\0';a++); for(d=0,b=(AB_Cntr-1);((PB[b]!=NEWLINE_CHAR)&&(b>0));b--,d++); // Let's insert it gracefully and not cut even 1 frame in half... if(AB_Cntr<(WORK_MEMORY_SIZE-a)) { #if 1 if((b>0)&&(b<32)) // Roll buffer to accomodate timestamp { ++b; // to move from 'NEWLINE_CHAR' to 't' for(c=0;c1) ActiveBank=0; *((unsigned int *)(SharedCommMemPtr+16))=AB_Cntr; kill(PidMain,SIGUSR1); AB_Cntr=0; PB=SharedDataMemPtr[ActiveBank]; for(a=0;Message[a]!='\0';a++) PB[AB_Cntr++]=Message[a]; } } void InsertCharacter(char Kar) { char* PB=SharedDataMemPtr[ActiveBank]; char Message[16]; int a,b,c,d; #ifdef COMM_DEBUG printf("\nkeystamp : %02x",Kar);fflush(stdout); #endif sprintf(Message,"tFFF0:%02x%c\0",Kar,NEWLINE_CHAR); // My ID of 0xFFF with 0 byte indicator, but :%c is info for(a=0;Message[a]!='\0';a++); for(d=0,b=AB_Cntr;((PB[b]!=NEWLINE_CHAR)&&(b>0));b--,d++); // Let's insert it gracefully and not cut even 1 frame in half... if(AB_Cntr<(WORK_MEMORY_SIZE-a)) { #if 1 if((b>0)&&(b<32)) // Roll buffer to accomodate timestamp { ++b; // to move from 'NEWLINE_CHAR' to 't' for(c=0;c1) ActiveBank=0; *((unsigned int *)(SharedCommMemPtr+16))=AB_Cntr; kill(PidMain,SIGUSR1); AB_Cntr=0; PB=SharedDataMemPtr[ActiveBank]; for(a=0;Message[a]!='\0';a++) PB[AB_Cntr++]=Message[a]; } } void GoodBye(void) { // Anything else need to be done ? } void SaveMemoryToDisk(int AB,unsigned int ThisMany) { char* PB=SharedDataMemPtr[AB]; int a; time_t t0; struct tm *ct; FILE *fp=NULL; char FileName[32]; DiskIO=1; t0=time(0); ct=localtime(&t0); sprintf(FileName,"%03d_%02d.%02d_%02d.%02d.%02d",ActiveFile,(ct->tm_mon)+1,ct->tm_mday,ct->tm_hour,ct->tm_min,ct->tm_sec); ActiveFile++; #ifndef COLL_DEBUG if((fp=fopen(FileName,"w"))==NULL) { printf("\nCan not open '%s' for writing...",FileName);fflush(stdout); return; } if(fwrite(PB,sizeof(char),(size_t)ThisMany,fp)!=ThisMany) { fseek(fp,0L,SEEK_SET); a=0; while(a QUIT request");fflush(stdout); #endif Maingo=0; break; case 253 : if(++SamplingIsStopped>1) SamplingIsStopped=0; if((!SamplingIsStopped)&&(StartTime==0)) { StartTime=time(NULL); printf("\nCollector STARTED sampling...");fflush(stdout); } else { printf("\nCollector '%s' sampling...",((SamplingIsStopped)?("SUSPENDED"):("RESUMED")));fflush(stdout); } break; case 252 : /* Engine : 7E080213B00000000000 response came 55 message later as : 7E880253 Cruise Ctrl : 7E080213800000000000 response came 55 message later as : 7E880253 HV : 7E280213B00000000000 response came 54 message later as : 7EA80253 Batt : 7E380213800000000000 response came 59 message later as : 7EB80253 for 7E2 : t7EA80253000000000000 after sending B0, this is t7EA8045301A799000000 No fault response is 0253000000000000 no response for 7E1/7E4 */ printf("\nMessage transmit request...");fflush(stdout); InsertCharacter('d'); // sprintf(Message,"t7E080213800000000000\015"); // sprintf(Message,"t7E080213800000000000\015"); // sprintf(Message,"t7E280213B00000000000\015"); sprintf(Message,"t7E380213800000000000\015"); WriteToPort(Message); break; case 251 : printf("\nMessage transmit more request...");fflush(stdout); InsertCharacter('m'); // sprintf(Message,"t7E083000000000000000\015"); // sprintf(Message,"t7E283000000000000000\015"); sprintf(Message,"t7E383000000000000000\015"); WriteToPort(Message); break; default : #ifdef COMM_DEBUG printf("\n Collector received info, character %c is to be inserted...",SharedCommMemPtr[0]);fflush(stdout); #endif InsertCharacter(SharedCommMemPtr[0]); break; } } signal(SIGUSR1,SigCatch); break; case SIGALRM : signal(SIGALRM,SigCatch); alarm(1); if(!SamplingIsStopped) InsertTimeStamp(); break; } } int GetSharedMemIds() { register key_t SMKey; switch(sizeof(key_t)) { case 0 : SMKey=(key_t)0;break; case 1 : SMKey=(key_t)0x42;break; case 2 : SMKey=(key_t)0x4268;break; case 3 : SMKey=(key_t)0x426817;break; default: SMKey=(key_t)0x42681712;break; } if((SharedDataMemId[0]=shmget(SMKey,(size_t)WORK_MEMORY_SIZE,0666|IPC_CREAT))==-1) { SMKey+=0xFF; if((SharedDataMemId[0]=shmget(SMKey,(size_t)WORK_MEMORY_SIZE,0666|IPC_CREAT))==-1) { SMKey+=0xFF; if((SharedDataMemId[0]=shmget(SMKey,(size_t)WORK_MEMORY_SIZE,0666|IPC_CREAT))==-1) { return(-1); } } } switch(sizeof(key_t)) { case 0 : SMKey=(key_t)0;break; case 1 : SMKey=(key_t)0x17;break; case 2 : SMKey=(key_t)0x1712;break; case 3 : SMKey=(key_t)0x171268;break; default: SMKey=(key_t)0x17126842;break; } if((SharedDataMemId[1]=shmget(SMKey,(size_t)WORK_MEMORY_SIZE,0666|IPC_CREAT))==-1) { SMKey+=0xFF; if((SharedDataMemId[1]=shmget(SMKey,(size_t)WORK_MEMORY_SIZE,0666|IPC_CREAT))==-1) { SMKey+=0xFF; if((SharedDataMemId[1]=shmget(SMKey,(size_t)WORK_MEMORY_SIZE,0666|IPC_CREAT))==-1) { return(-1); } } } switch(sizeof(key_t)) { case 0 : SMKey=(key_t)0;break; case 1 : SMKey=(key_t)0x68;break; case 2 : SMKey=(key_t)0x6812;break; case 3 : SMKey=(key_t)0x681217;break; default: SMKey=(key_t)0x68121742;break; } if((SharedCommMemId=shmget(SMKey,(size_t)COMM_MEMORY_SIZE,0666|IPC_CREAT))==-1) { SMKey+=0xFF; if((SharedCommMemId=shmget(SMKey,(size_t)COMM_MEMORY_SIZE,0666|IPC_CREAT))==-1) { SMKey+=0xFF; if((SharedCommMemId=shmget(SMKey,(size_t)COMM_MEMORY_SIZE,0666|IPC_CREAT))==-1) { return(-1); } } } return(0); } void SetUpSignals() { signal(SIGINT,SigCatch); signal(SIGHUP,SigCatch); signal(SIGTERM,SigCatch); signal(SIGBUS,SigCatch); signal(SIGSEGV,SigCatch); signal(SIGQUIT,SigCatch); signal(SIGUSR1,SigCatch); } int RunMain(void) { struct termios oldT,newT; int a,flag; PidMine=PidMain; printf("\n---Running Main Process with %d (%d,%d)",PidMine,PidMain,PidCollector);fflush(stdout); if((SharedDataMemPtr[0]=(char*)shmat(SharedDataMemId[0],0,0))==NULL) { printf("\n%d : Can not attach Shared Memory Data_0...",PidMine);fflush(stdout); return(0); } if((SharedDataMemPtr[1]=(char*)shmat(SharedDataMemId[1],0,0))==NULL) { printf("\n%d : Can not attach Shared Memory Data_1...",PidMine);fflush(stdout); return(0); } if((SharedCommMemPtr=(char*)shmat(SharedCommMemId,0,0))==NULL) { printf("\n%d : Can not attach Shared Memory Comm...",PidMine);fflush(stdout); return(0); } SetUpSignals(); ioctl(0,TCGETS,&oldT); ioctl(0,TCGETS,&newT); newT.c_lflag&=~ECHO; newT.c_lflag&=~ICANON; ioctl(0,TCSETS,&newT); printf("\n\t'z' is to toggle sampling..."); printf("\n\t'Esc' is to quit...");fflush(stdout); printf("\n\tOther keys will be inserted in datastream as 0xFFF message ID...\n"); printf("\n### WAIT FOR COLLECTOR, PLEASE!!! ###");fflush(stdout); while(Maingo) { a=getchar(); //printf("\n%d = '%c' %d",PidMine,a,a);fflush(stdout); switch(a) { case 27 : SharedCommMemPtr[0]=(unsigned char)254; // Special Signal to quit kill(PidCollector,SIGUSR1); break; case 'z' : case 'Z' : SharedCommMemPtr[0]=(unsigned char)253; // Special Signal to suspend/restart kill(PidCollector,SIGUSR1); break; case 'd' : SharedCommMemPtr[0]=(unsigned char)252; // Special Signal to send kill(PidCollector,SIGUSR1); break; case 'm' : SharedCommMemPtr[0]=(unsigned char)251; // Special Signal to send kill(PidCollector,SIGUSR1); break; default : SharedCommMemPtr[0]=(unsigned char)a; kill(PidCollector,SIGUSR1); break; } } printf("\n---Main Quit Gracefully ...\n");fflush(stdout); ioctl(0,TCSETS,&oldT); shmdt(SharedDataMemPtr[0]); shmdt(SharedDataMemPtr[1]); shmdt(SharedCommMemPtr); return(1); } void SignalDummyQuit() { SharedCommMemPtr[1]=ActiveBank; SharedCommMemPtr[2]='Q'; *((unsigned int *)(SharedCommMemPtr+16))=0; *((unsigned int *)(SharedCommMemPtr+32))=0; kill(PidMain,SIGUSR1); } int RunCollector(void) { int to,a; char* PB; time_t EndTime; unsigned int timdi=0; if((PidMine=getpid())==-1) { printf("\nERROR : Can NOT obtain Collector ID on process...\n"); fflush(stdout); SignalDummyQuit(); return(1); } // setpriority(PRIO_PROCESS,PidMine,-9); if((SharedDataMemPtr[0]=(char*)shmat(SharedDataMemId[0],0,0))==NULL) { printf("\n%d : Can not attach Shared Memory Data_0...",PidMine);fflush(stdout); SignalDummyQuit(); return(0); } if((SharedDataMemPtr[1]=(char*)shmat(SharedDataMemId[1],0,0))==NULL) { printf("\n%d : Can not attach Shared Memory Data_1...",PidMine);fflush(stdout); SignalDummyQuit(); shmdt(SharedDataMemPtr[0]); return(0); } if((SharedCommMemPtr=(char*)shmat(SharedCommMemId,0,0))==NULL) { printf("\n%d : Can not attach Shared Memory Comm...",PidMine);fflush(stdout); SignalDummyQuit(); shmdt(SharedDataMemPtr[0]); shmdt(SharedDataMemPtr[1]); return(0); } SetUpSignals(); printf("\n---Running Collector with %d (%d,%d)",PidMine,PidMain,PidCollector);fflush(stdout); #ifndef COLL_DEBUG if(OpenAndConfigurePort()) { SignalDummyQuit(); shmdt(SharedDataMemPtr[0]); shmdt(SharedDataMemPtr[1]); shmdt(SharedCommMemPtr); return(0); } sprintf(Message,"\015\015\015"); WriteToPort(Message); for(a=0;a<10000;a++) to=a; sprintf(Message,"V\015"); // get version WriteToPort(Message); for(a=0;a<10000;a++) to=a; sprintf(Message,"N\015"); // get Serial WriteToPort(Message); for(a=0;a<10000;a++) to=a; sprintf(Message,"S6\015"); // CAN with 500Kbps S0-10 S1-20 S2-50 S3-100 S4-125 S5-250 S7-800 S8-1M WriteToPort(Message); sprintf(Message,"O\015"); // Open the CAN channel WriteToPort(Message); #endif signal(SIGALRM,SigCatch); alarm(1); if(!SamplingIsStopped) { StartTime=time(NULL); printf("\nSampling is RUNNING..."); } else { printf("\nSampling is SUSPENDED, activate with 'z' !"); } fflush(stdout); SharedCommMemPtr[1]=ActiveBank; while(Maingo) { if(Poll()) { // sleep(1); // printf("\n%d : '%c'",PidMine,*(SharedMemoryPtr));fflush(stdout); } } #ifndef COLL_DEBUG sprintf(Message,"C\015"); // Close the CAN channel WriteToPort(Message); if(Port>=0) close(Port); #endif printf("\n---Collector Quit Gracefully [%d:%d]...",ActiveBank,AB_Cntr);fflush(stdout); EndTime=time(NULL); timdi=(unsigned int)difftime(EndTime,StartTime); SharedCommMemPtr[1]=ActiveBank; SharedCommMemPtr[2]='Q'; *((unsigned int *)(SharedCommMemPtr+16))=AB_Cntr; *((unsigned int *)(SharedCommMemPtr+32))=timdi; kill(PidMain,SIGUSR1); AB_Cntr=0; //printf("\n\nSampling was for %d seconds... ( %2.2f minutes )",timdi,((float)timdi/60.0f));fflush(stdout); shmdt(SharedDataMemPtr[0]); shmdt(SharedDataMemPtr[1]); shmdt(SharedCommMemPtr); return(1); } int main (int argc,char **argv) { if(argc>1) { SamplingIsStopped=1; } if(GetSharedMemIds()==-1) { printf("\nERROR for SharedMemoryKey...\n"); fflush(stdout); return(1); } #ifdef COMM_DEBUG printf("\nSharedMemoryIDs : %d %d %d",SharedDataMemId[0],SharedDataMemId[1],SharedCommMemId);fflush(stdout); #endif if(shmctl(SharedDataMemId[0],IPC_STAT,&SMMyInfo)==-1) { printf("\nError For SM-Info for DataBank0.");fflush(stdout); shmctl(SharedDataMemId[0],IPC_RMID,0); shmctl(SharedDataMemId[1],IPC_RMID,0); shmctl(SharedCommMemId,IPC_RMID,0); return(1); } if(shmctl(SharedDataMemId[1],IPC_STAT,&SMMyInfo)==-1) { printf("\nError For SM-Info for DataBank1.");fflush(stdout); shmctl(SharedDataMemId[0],IPC_RMID,0); shmctl(SharedDataMemId[1],IPC_RMID,0); shmctl(SharedCommMemId,IPC_RMID,0); return(1); } if(shmctl(SharedCommMemId,IPC_STAT,&SMMyInfo)==-1) { printf("\nError For SM-Info for CommBank");fflush(stdout); shmctl(SharedDataMemId[0],IPC_RMID,0); shmctl(SharedDataMemId[1],IPC_RMID,0); shmctl(SharedCommMemId,IPC_RMID,0); return(1); } if((PidMain=getpid())==-1) { printf("\nERROR : Can NOT obtain information on process...\n"); fflush(stdout); return(1); } printf("\nMainProcess: %d",PidMain);fflush(stdout); #if COMM_DEBUG printf("\nCId : %d (%d) <%d>",SMMyInfo.shm_cpid,PidMain,SMMyInfo.shm_segsz);fflush(stdout); #endif zerotime(); switch((PidCollector=fork())) { case -1 : printf("\nERROR : Can NOT fork process...\n");fflush(stdout); shmctl(SharedDataMemId[0],IPC_RMID,0); shmctl(SharedDataMemId[1],IPC_RMID,0); shmctl(SharedCommMemId,IPC_RMID,0); return(1); default : RunMain(); shmctl(SharedDataMemId[0],IPC_RMID,0); shmctl(SharedDataMemId[1],IPC_RMID,0); shmctl(SharedCommMemId,IPC_RMID,0); break; case 0 : sleep(1); RunCollector(); break; } GoodBye(); //printf("\nEND. (%d)\n",PidMine);fflush(stdout); }