/************************************************************************ * flight_recorder.c ************************************************************************ * This code supports the a generic flight recorder. * * Copyright (C) 20yy * * * * 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., * * 59 Temple Place, Suite 330, * * Boston, MA 02111-1307 USA * ************************************************************************ * This is a simple text based flight recorder. Useful for logging * information the you may want to retreive at a latter time. Errors or * debug inforamtion are good examples. A good method to dump the * information is via the proc file system. * * To use. * 1. Create the flight recorder object. Passing a NULL pointer will * kmalloc the space for you. If it is too early for kmalloc, create * space for the object. Beware, don't lie about the size, you will * pay for that later. * FlightRecorder* TestFr = alloc_Flight_Recorder(NULL,"TestFr",4096); * * 2. Log any notable events, initialzation, error conditions, etc. * LOGFR(TestFr,"5. Stack Variable(10) %d",StackVariable); * * 3. Dump the information to a buffer. * fr_Dump(TestFr, proc_file_buffer, proc_file_buffer_size); * ************************************************************************/ #include #include #include #include #include #include #include static char LogText[512]; static int LogTextIndex; static int LogCount = 0; static spinlock_t Fr_Lock; /************************************************************************ * Build the log time prefix based on Flags. * 00 = No time prefix * 01 = Date(mmddyy) Time(hhmmss) prefix * 02 = Day(dd) Time(hhmmss) prefix * 03 = Time(hhmmss) prefix ************************************************************************/ static void fr_Log_Time(FlightRecorder* Fr) { struct timeval TimeClock; struct rtc_time LogTime; do_gettimeofday(&TimeClock); to_tm(TimeClock.tv_sec, &LogTime); if (Fr->Flags == 1) { LogTextIndex = sprintf(LogText,"%02d%02d%02d %02d%02d%02d ", LogTime.tm_mon, LogTime.tm_mday, LogTime.tm_year-2000, LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec); } else if (Fr->Flags == 2) { LogTextIndex = sprintf(LogText,"%02d %02d%02d%02d ", LogTime.tm_mday, LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec); } else if (Fr->Flags == 3) { LogTextIndex = sprintf(LogText,"%02d%02d%02d ", LogTime.tm_hour,LogTime.tm_min, LogTime.tm_sec); } else { ++LogCount; LogTextIndex = sprintf(LogText,"%04d. ",LogCount); } } /************************************************************************/ /* Log entry into buffer, */ /* ->If entry is going to wrap, log "WRAP" and start at the top. */ /************************************************************************/ static void fr_Log_Data(FlightRecorder* Fr) { int TextLen = strlen(LogText); int Residual = ( Fr->EndPointer - Fr->NextPointer)-15; if (TextLen > Residual) { strcpy(Fr->NextPointer,"WRAP"); Fr->WrapPointer = Fr->NextPointer + 5; Fr->NextPointer = Fr->StartPointer; } strcpy(Fr->NextPointer,LogText); Fr->NextPointer += TextLen+1; strcpy(Fr->NextPointer,"<="); } /************************************************************************ * Build the log text, support variable args. ************************************************************************/ void fr_Log_Entry(struct flightRecorder* LogFr, const char *fmt, ...) { va_list arg_ptr; spin_lock(&Fr_Lock); fr_Log_Time(LogFr); va_start(arg_ptr, fmt); vsprintf(LogText+LogTextIndex, fmt, arg_ptr); va_end(arg_ptr); fr_Log_Data(LogFr); spin_unlock(&Fr_Lock); } /************************************************************************ * Dump Flight Recorder into buffer. * -> Handles the buffer wrapping. ************************************************************************/ int fr_Dump(FlightRecorder* Fr, char *Buffer, int BufferLen) { int LineLen = 0; char* StartEntry; char* EndEntry; spin_lock(&Fr_Lock); /**************************************************************** * If Buffer has wrapped, find last usable entry to start with. ****************************************************************/ if (Fr->WrapPointer != NULL) { StartEntry = Fr->NextPointer+3; StartEntry += strlen(StartEntry)+1; EndEntry = Fr->WrapPointer; while (EndEntry > StartEntry && LineLen < BufferLen) { LineLen += sprintf(Buffer+LineLen,"%s\n",StartEntry); StartEntry += strlen(StartEntry) + 1; } } /**************************************************************** * Dump from the beginning to the last logged entry ****************************************************************/ StartEntry = Fr->StartPointer; EndEntry = Fr->NextPointer; while (EndEntry > StartEntry && LineLen < BufferLen) { LineLen += sprintf(Buffer+LineLen,"%s\n",StartEntry); StartEntry += strlen(StartEntry) + 1; } spin_unlock(&Fr_Lock); return LineLen; } /************************************************************************ * Allocate and Initialized the Flight Recorder * -> If no FlightRecorder pointer is passed, the space is kmalloc. ************************************************************************/ FlightRecorder* alloc_Flight_Recorder(FlightRecorder* FrPtr, char* Signature, int SizeOfFr) { FlightRecorder* Fr = FrPtr; /* Pointer to Object */ int FrSize = (SizeOfFr/16)*16; /* Could be static */ if (Fr == NULL) Fr = (FlightRecorder*)kmalloc(SizeOfFr, GFP_KERNEL); memset(Fr,0,SizeOfFr); strcpy(Fr->Signature,Signature); Fr->Size = FrSize; Fr->Flags = 0; Fr->StartPointer = (char*)&Fr->Buffer; Fr->EndPointer = (char*)Fr + Fr->Size; Fr->NextPointer = Fr->StartPointer; fr_Log_Entry(Fr,"Initialized."); return Fr; }