From d46b090771291c10127d0fb421ee3c9f1e8f69b1 Mon Sep 17 00:00:00 2001 From: Michael Giacomelli Date: Tue, 3 Jul 2012 21:45:29 -0400 Subject: Introduce logging to disk feature into rockbox. Logs information, errors, etc to disk using the register_storage_idle_func mechanism to write to the disk when available. Currently, this is disabled in normal builds, but can be enabled by adding ROCKBOX_HAS_LOGDISKF to the config file. By default, it uses a 2KB buffer and drops text if the buffer overflows. The system includes a simple warning level mechanism that can be used to by default exclude non-serious errors from logging on release builds. Change-Id: I0a3d186a93625c7c93dae37b993a0d37e5a3a925 Reviewed-on: http://gerrit.rockbox.org/288 Reviewed-by: Jonathan Gordon Tested-by: Michael Giacomelli Reviewed-by: Michael Giacomelli --- apps/main.c | 5 ++ firmware/SOURCES | 2 +- firmware/export/logdiskf.h | 81 ++++++++++++++++++++++++++++ firmware/logf.c | 129 ++++++++++++++++++++++++++++++++++++--------- 4 files changed, 190 insertions(+), 27 deletions(-) create mode 100644 firmware/export/logdiskf.h diff --git a/apps/main.c b/apps/main.c index 4ce72497d7..6b6566c7ca 100644 --- a/apps/main.c +++ b/apps/main.c @@ -76,6 +76,7 @@ #include "skin_engine/skin_engine.h" #include "statusbar-skinned.h" #include "bootchart.h" +#include "logdiskf.h" #if (CONFIG_PLATFORM & PLATFORM_ANDROID) #include "notification.h" #endif @@ -489,6 +490,10 @@ static void init(void) #endif #endif +#ifdef ROCKBOX_HAS_LOGDISKF + init_logdiskf(); +#endif + #if CONFIG_RTC rtc_init(); #endif diff --git a/firmware/SOURCES b/firmware/SOURCES index 80267b4320..98b09738af 100644 --- a/firmware/SOURCES +++ b/firmware/SOURCES @@ -26,7 +26,7 @@ target/hosted/debug-hosted.c #endif system.c usb.c -#ifdef ROCKBOX_HAS_LOGF +#if defined(ROCKBOX_HAS_LOGF) || defined(ROCKBOX_HAS_LOGDISKF) logf.c #endif /* ROCKBOX_HAS_LOGF */ kernel.c diff --git a/firmware/export/logdiskf.h b/firmware/export/logdiskf.h new file mode 100644 index 0000000000..628662fdba --- /dev/null +++ b/firmware/export/logdiskf.h @@ -0,0 +1,81 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2012 by Michael Giacomelli + * + * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef LOGDISKF_H +#define LOGDISKF_H +#include +#include +#include "gcc_extensions.h" +#include "debug.h" + +#ifdef ROCKBOX_HAS_LOGDISKF + +void init_logdiskf(void); + +#ifndef __PCTOOL__ + +/*large memory devices spin up the disk much less often*/ +#if MEMORYSIZE > 32 + #define MAX_LOGDISKF_SIZE 8192 +#elif MEMORYSIZE > 8 + #define MAX_LOGDISKF_SIZE 4096 +#else + #define MAX_LOGDISKF_SIZE 1024 +#endif + +extern unsigned char logdiskfbuffer[MAX_LOGDISKF_SIZE]; +extern int logfdiskindex; +#endif /* __PCTOOL__ */ + + +#define LOGDISK_LEVEL 1 + +#if LOGDISK_LEVEL > 0 /*serious errors or problems*/ + #define ERRORF(...) _logdiskf(__func__,'E', __VA_ARGS__) +#else + #define ERRORF(...) +#endif + +#if LOGDISK_LEVEL > 1 /*matters of concern*/ + #define WARNF(...) _logdiskf(__func__, 'W', __VA_ARGS__) +#else + #define WARNF(...) +#endif + +#if LOGDISK_LEVEL > 2 /*useful for debug only*/ + #define NOTEF(...) _logdiskf(__func__, 'N', __VA_ARGS__) +#else + #define NOTEF(...) /*TODO: rename DEBUGF later*/ +#endif + +/*__FILE__ would be better but is difficult to make work with the build system*/ +//#define logdiskf(...) _logdiskf(__func__, 1, __VA_ARGS__) + +void _logdiskf(const char* file, const char level, + const char *format, ...) ATTRIBUTE_PRINTF(3, 4); + +#else /* !ROCKBOX_HAS_LOGF */ + +/* built without logdiskf() support enabled, replace logdiskf() by DEBUGF() */ +#define logdiskf(f,args...) DEBUGF(f"\n",##args) + +#endif /* !ROCKBOX_HAS_LOGDISKF */ + +#endif /* LOGDISKF_H */ diff --git a/firmware/logf.c b/firmware/logf.c index fc81ced779..23af33d076 100644 --- a/firmware/logf.c +++ b/firmware/logf.c @@ -44,6 +44,16 @@ #include "usbstack/usb_serial.h" #endif +#ifdef ROCKBOX_HAS_LOGDISKF +#include "logdiskf.h" +#include "file.h" +#include "rbpaths.h" +#include "ata_idle_notify.h" + +unsigned char logdiskfbuffer[MAX_LOGDISKF_SIZE]; +int logdiskfindex; +#endif + /* Only provide all this if asked to */ #ifdef ROCKBOX_HAS_LOGF @@ -68,33 +78,33 @@ static void displayremote(void) I hope there is no font with height < 6 ! */ const int NB_ENTRIES=LCD_REMOTE_HEIGHT / 6; int line_start_ptr[NB_ENTRIES]; - + fontnr = lcd_getfont(); font = font_get(fontnr); - + /* get the horizontal size of each line */ font_getstringsize("A", NULL, &delta_y, fontnr); - + /* font too small ? */ if(delta_y < 6) return; /* nothing to print ? */ if(logfindex == 0 && !logfwrap) return; - + w = LCD_REMOTE_WIDTH; h = LCD_REMOTE_HEIGHT; nb_lines = 0; - + if(logfwrap) i = logfindex; else i = 0; - + cur_x = 0; - + line_start_ptr[0] = i; - + do { if(logfbuffer[i] == '\0') @@ -106,7 +116,7 @@ static void displayremote(void) { /* does character fit on this line ? */ delta_x = font_get_width(font, logfbuffer[i]); - + if(cur_x + delta_x > w) { cur_x = 0; @@ -119,14 +129,14 @@ static void displayremote(void) if(i >= MAX_LOGF_SIZE) i = 0; } while(i != logfindex); - + lcd_remote_clear_display(); - + i = line_start_ptr[ MAX(nb_lines - h / delta_y, 0) % NB_ENTRIES]; cur_x = 0; cur_y = 0; buf[1] = '\0'; - + do { if(logfbuffer[i] == '\0') { @@ -137,24 +147,24 @@ static void displayremote(void) { /* does character fit on this line ? */ delta_x = font_get_width(font, logfbuffer[i]); - + if(cur_x + delta_x > w) { cur_y += delta_y; cur_x = 0; } - + buf[0] = logfbuffer[i]; lcd_remote_putsxy(cur_x, cur_y, buf); cur_x += delta_x; } - + i++; if(i >= MAX_LOGF_SIZE) i = 0; } while(i != logfindex); - - lcd_remote_update(); + + lcd_remote_update(); } #else #define displayremote() @@ -166,14 +176,14 @@ void _logf(const char *format, ...) char buf[1024]; va_list ap; va_start(ap, format); - + vsnprintf(buf, sizeof buf, format, ap); printf("DEBUG: %s\n", buf); } #else static void check_logfindex(void) { - if(logfindex >= MAX_LOGF_SIZE) + if(logfindex >= MAX_LOGF_SIZE) { /* wrap */ logfwrap = true; @@ -184,10 +194,10 @@ static void check_logfindex(void) static int logf_push(void *userp, unsigned char c) { (void)userp; - + logfbuffer[logfindex++] = c; check_logfindex(); - + #if defined(HAVE_SERIAL) && !defined(SIMULATOR) && defined(LOGF_SERIAL) if(c != '\0') { @@ -197,7 +207,7 @@ static int logf_push(void *userp, unsigned char c) serial_tx(buf); } #endif - + return true; } @@ -209,7 +219,7 @@ void _logf(const char *fmt, ...) va_list ap; va_start(ap, fmt); - + #if (CONFIG_PLATFORM & PLATFORM_HOSTED) char buf[1024]; vsnprintf(buf, sizeof buf, fmt, ap); @@ -221,10 +231,10 @@ void _logf(const char *fmt, ...) vuprintf(logf_push, NULL, fmt, ap); va_end(ap); - + /* add trailing zero */ logf_push(NULL, '\0'); - + #if defined(HAVE_SERIAL) && !defined(SIMULATOR) && defined(LOGF_SERIAL) serial_tx("\r\n"); #endif @@ -238,10 +248,77 @@ void _logf(const char *fmt, ...) else usb_serial_send(logfbuffer + old_logfindex, logfindex - old_logfindex - 1); usb_serial_send("\r\n", 2); -#endif +#endif displayremote(); } #endif #endif + +#ifdef ROCKBOX_HAS_LOGDISKF +static int logdiskf_push(void *userp, unsigned char c) +{ + (void)userp; + + /*just stop logging if out of space*/ + if(logdiskfindex>=MAX_LOGDISKF_SIZE-1) + { + strcpy(&logdiskfbuffer[logdiskfindex-8], "LOGFULL"); + logdiskfindex=MAX_LOGDISKF_SIZE; + return false; + } + logdiskfbuffer[logdiskfindex++] = c; + + return true; +} + +void _logdiskf(const char* file, const char level, const char *fmt, ...) +{ + + va_list ap; + + va_start(ap, fmt); + int len =strlen(file); + if(logdiskfindex +len + 4 > MAX_LOGDISKF_SIZE-1) + { + strcpy(&logdiskfbuffer[logdiskfindex-8], "LOGFULL"); + logdiskfindex=MAX_LOGDISKF_SIZE; + return; + } + + logdiskf_push(NULL, level); + logdiskf_push(NULL, ' '); + logdiskf_push(NULL, '['); + strcpy(&logdiskfbuffer[logdiskfindex], file); + logdiskfindex += len; + logdiskf_push(NULL, ']'); + + vuprintf(logdiskf_push, NULL, fmt, ap); + va_end(ap); + + +} +static void flush_buffer(void* data) +{ + (void)data; + int fd; + if(logdiskfindex < 1) + return; + + fd = open(HOME_DIR"/rockbox_log.txt", O_RDWR | O_CREAT | O_APPEND, 0666); + if (fd < 0) + return; + + write(fd, logdiskfbuffer, logdiskfindex); + close(fd); + + logdiskfindex = 0; +} + +void init_logdiskf() +{ + register_storage_idle_func(flush_buffer); +} + +#endif \ No newline at end of file -- cgit v1.2.3