Index: apps/debug_menu.c =================================================================== RCS file: /cvsroot/rockbox/apps/debug_menu.c,v retrieving revision 1.187 diff -u -r1.187 debug_menu.c --- apps/debug_menu.c 25 May 2006 13:34:51 -0000 1.187 +++ apps/debug_menu.c 3 Jun 2006 13:39:30 -0000 @@ -53,6 +53,7 @@ #include "tagcache.h" #include "lcd-remote.h" #include "crc32.h" +#include "logf" #ifdef HAVE_LCD_BITMAP #include "widgets.h" Index: apps/logfdisp.c =================================================================== RCS file: /cvsroot/rockbox/apps/logfdisp.c,v retrieving revision 1.9 diff -u -r1.9 logfdisp.c --- apps/logfdisp.c 11 Apr 2006 22:19:47 -0000 1.9 +++ apps/logfdisp.c 3 Jun 2006 13:39:30 -0000 @@ -18,7 +18,6 @@ ****************************************************************************/ #include "config.h" -#ifdef ROCKBOX_HAS_LOGF #include #include #include @@ -29,6 +28,7 @@ #include #include "menu.h" #include "logf.h" +#include "settings.h" #if CONFIG_KEYPAD == IPOD_4G_PAD #define LOGF_BUTTON_QUIT BUTTON_MENU @@ -38,10 +38,12 @@ #define LOGF_BUTTON_QUIT BUTTON_OFF #endif + #ifdef HAVE_LCD_BITMAP bool logfdisplay(void) { +#if 0 int w, h; int lines; int columns; @@ -95,7 +97,7 @@ lcd_update(); button = button_get_w_tmo(HZ/2); } while(button != LOGF_BUTTON_QUIT); - +#endif return false; } #else /* HAVE_LCD_BITMAP */ @@ -107,40 +109,3 @@ } #endif /* HAVE_LCD_BITMAP */ -/* Store the logf log to logf.txt in the .rockbox directory. The order of the - * entries will be "reversed" so that the most recently logged entry is on the - * top of the file */ -bool logfdump(void) -{ - int fd; - - if(!logfindex && !logfwrap) - /* nothing is logged just yet */ - return false; - - fd = open("/.rockbox/logf.txt", O_CREAT|O_WRONLY|O_TRUNC); - if(-1 != fd) { - unsigned char buffer[MAX_LOGF_ENTRY +1]; - int index = logfindex-1; - int stop = logfindex; - - - while(index != stop) { - if(index < 0) { - if(logfwrap) - index = MAX_LOGF_LINES-1; - else - break; /* done */ - } - - memcpy(buffer, logfbuffer[index], MAX_LOGF_ENTRY); - buffer[MAX_LOGF_ENTRY]=0; - fdprintf(fd, "%s\n", buffer); - index--; - } - close(fd); - } - return false; -} - -#endif /* ROCKBOX_HAS_LOGF */ Index: apps/logfdisp.h =================================================================== RCS file: /cvsroot/rockbox/apps/logfdisp.h,v retrieving revision 1.3 diff -u -r1.3 logfdisp.h --- apps/logfdisp.h 1 Jun 2005 13:07:37 -0000 1.3 +++ apps/logfdisp.h 3 Jun 2006 13:39:30 -0000 @@ -18,8 +18,8 @@ ****************************************************************************/ #ifndef LOGFDISP_H #define LOGFDISP_H +#include "logf.h" bool logfdisplay(void); -bool logfdump(void); #endif /* LOGFDISP_H */ Index: apps/settings.c =================================================================== RCS file: /cvsroot/rockbox/apps/settings.c,v retrieving revision 1.388 diff -u -r1.388 settings.c --- apps/settings.c 30 May 2006 11:26:40 -0000 1.388 +++ apps/settings.c 3 Jun 2006 13:39:34 -0000 @@ -80,6 +80,7 @@ #ifdef CONFIG_TUNER #include "radio.h" #endif +#include "logf.h" #if CONFIG_CODEC == MAS3507D void dac_line_in(bool enable); @@ -565,7 +566,7 @@ /* If values are just added to the end, no need to bump the version. */ /* new stuff to be added at the end */ - + {16, S_O(log_level), 0, "log_level", NULL }, /* Sum of all bit sizes must not grow beyond 0xB8*8 = 1472 */ }; @@ -1169,6 +1170,7 @@ set_remote_backlight_filter_keypress(global_settings.remote_bl_filter_first_keypress); #endif #endif + set_log_level(global_settings.log_level); } Index: apps/settings.h =================================================================== RCS file: /cvsroot/rockbox/apps/settings.h,v retrieving revision 1.219 diff -u -r1.219 settings.h --- apps/settings.h 25 May 2006 13:34:51 -0000 1.219 +++ apps/settings.h 3 Jun 2006 13:39:35 -0000 @@ -495,6 +495,7 @@ #ifdef HAVE_LCD_BITMAP unsigned char kbd_file[MAX_FILENAME+1]; /* last keyboard */ #endif + short int log_level; }; enum optiontype { INT, BOOL }; Index: apps/settings_menu.c =================================================================== RCS file: /cvsroot/rockbox/apps/settings_menu.c,v retrieving revision 1.256 diff -u -r1.256 settings_menu.c --- apps/settings_menu.c 29 May 2006 05:19:18 -0000 1.256 +++ apps/settings_menu.c 3 Jun 2006 13:39:36 -0000 @@ -55,6 +55,9 @@ #include "yesno.h" #include "list.h" #include "color_picker.h" +#include "logf.h" +#include "logfdisp.h" +#include "gui/splash.h" #ifdef HAVE_LCD_BITMAP #include "peakmeter.h" @@ -1952,7 +1955,132 @@ return result; } +void set_loglvl_format(char* buffer, int buffer_size, int value, + const char* unit) +{ + switch (value) + { + case SYSLOG_LVL_INFO: + snprintf(buffer,buffer_size,"Information or worse"); + break; + case SYSLOG_LVL_ATTENTION: + snprintf(buffer,buffer_size,"Attention or worse"); + break; + case SYSLOG_LVL_NOTICE: + snprintf(buffer,buffer_size,"Notice or worse"); + break; + case SYSLOG_LVL_WARNING: + snprintf(buffer,buffer_size,"Warning or worse"); + break; + case SYSLOG_LVL_ERROR: + snprintf(buffer,buffer_size,"Error or worse"); + break; + case SYSLOG_LVL_URGENT: + snprintf(buffer,buffer_size,"Urgent Or Critial"); + break; + case SYSLOG_LVL_CRITICAL: + snprintf(buffer,buffer_size,"Everything"); + break; + case SYSLOG_LVL_NONE: + snprintf(buffer,buffer_size,"OFF"); + break; + } +} +bool set_loglvl(void) +{ + int level = global_settings.log_level&(~SYSLOG_SUBSYSTEM_MASK); + bool result = set_int("Log Level", "", + 0, &level, NULL, 1, 0, 7, + set_loglvl_format); + + global_settings.log_level = (global_settings.log_level&(SYSLOG_SUBSYSTEM_MASK)) + &level; + return result; + +} +bool set_logsystems(void) +{ + int m, systems = global_settings.log_level&(SYSLOG_SUBSYSTEM_MASK); + bool result; + int r; + static const struct menu_item items[] = { + { "All On", NULL }, + { "All Off", NULL }, + { "Main Thread", NULL }, + { "Playback", NULL }, + { "LCD", NULL }, + { "Plugin", NULL }, + { "Codec", NULL }, + { "Power", NULL }, + { "Others", NULL } + }; + m=menu_init( items, sizeof items / sizeof(struct menu_item), NULL, + NULL, NULL, NULL); + r = menu_show(m); + switch (r) + { + case 0: + systems = SYSLOG_SUBSYSTEM_MASK; + gui_syncsplash(HZ/2,true,"All On"); + break; + case 1: + systems = 0; + gui_syncsplash(HZ/2,true,"All Off"); + break; + case 2: + gui_syncsplash(HZ/2,true,systems&SYSLOG_SYS_MAIN_THREAD?"Not Monitoring":"Monitoring"); + systems |= SYSLOG_SYS_MAIN_THREAD; + break; + case 3: + gui_syncsplash(HZ/2,true,systems&SYSLOG_SYS_PLAYBACK?"Not Monitoring":"Monitoring"); + systems |= SYSLOG_SYS_PLAYBACK; + break; + case 4: + gui_syncsplash(HZ/2,true,systems&SYSLOG_SYS_LCD?"Not Monitoring":"Monitoring"); + systems |= SYSLOG_SYS_LCD; + break; + case 5: + gui_syncsplash(HZ/2,true,systems&SYSLOG_SYS_PLUGIN?"Not Monitoring":"Monitoring"); + systems |= SYSLOG_SYS_PLUGIN; + break; + case 6: + gui_syncsplash(HZ/2,true,systems&SYSLOG_SYS_CODEC?"Not Monitoring":"Monitoring");; + systems |= SYSLOG_SYS_CODEC; + break; + case 7: + gui_syncsplash(HZ/2,true,systems&SYSLOG_SYS_POWER?"Not Monitoring":"Monitoring"); + systems |= SYSLOG_SYS_POWER; + break; + case 8: + gui_syncsplash(HZ/2,true,systems&SYSLOG_SYS_OTHER?"Not Monitoring":"Monitoring"); + systems |= SYSLOG_SYS_OTHER; + break; + } + global_settings.log_level = (global_settings.log_level&(~SYSLOG_SUBSYSTEM_MASK)) + &systems; + set_log_level(global_settings.log_level); + menu_exit(m); + + return false; +} + +bool dbg_log(void) +{ + int m; + bool result; + static const struct menu_item items[] = { + { "View System Log", logfdisplay }, + { "Dump System Log To Disk", logfdump }, + { "Change Log Level", set_loglvl }, + { "Change Monitored Systems", set_logsystems } + }; + m=menu_init( items, sizeof items / sizeof(struct menu_item), NULL, + NULL, NULL, NULL); + result = menu_run(m); + menu_exit(m); + return result; +} static bool system_settings_menu(void) { int m; @@ -1978,6 +2106,7 @@ #ifdef HAVE_CHARGING { ID2P(LANG_CAR_ADAPTER_MODE), car_adapter_mode }, #endif +{ "System Log", dbg_log }, }; m=menu_init( items, sizeof(items) / sizeof(*items), NULL, Index: firmware/logf.c =================================================================== RCS file: /cvsroot/rockbox/firmware/logf.c,v retrieving revision 1.8 diff -u -r1.8 logf.c --- firmware/logf.c 30 Jun 2005 15:14:33 -0000 1.8 +++ firmware/logf.c 3 Jun 2006 13:39:38 -0000 @@ -18,7 +18,7 @@ ****************************************************************************/ /* - * logf() logs MAX_LOGF_ENTRY (21) bytes per entry in a circular buffer. Each + * logf() logs MAX_LOGF_ENTRY bytes per entry in a circular buffer. Each * logged string is space- padded for easier and faster output on screen. Just * output MAX_LOGF_ENTRY characters on each line. MAX_LOGF_ENTRY bytes fit * nicely on the iRiver remote LCD (128 pixels with an 8x6 pixels font). @@ -31,18 +31,18 @@ #include "config.h" #include "lcd-remote.h" #include "logf.h" +#include "file.h" -/* Only provide all this if asked to */ -#ifdef ROCKBOX_HAS_LOGF -unsigned char logfbuffer[MAX_LOGF_LINES][MAX_LOGF_ENTRY]; -int logfindex; -bool logfwrap; +char logfbuffer[MAX_LOGF_CHARS]; +int log_start = 0; +short int log_level = SYSLOG_EVERYTHING; + #ifdef HAVE_REMOTE_LCD static void displayremote(void) { - /* TODO: we should have a debug option that enables/disables this! */ +#if 0 int w, h; int lines; int columns; @@ -65,39 +65,85 @@ else break; /* done */ } - + memcpy(buffer, logfbuffer[index], columns); buffer[columns]=0; lcd_remote_puts(0, i, buffer); } - lcd_remote_update(); + lcd_remote_update(); +#endif } #else #define displayremote() #endif - -void logf(const char *format, ...) +void syslogf(const short int level, const char *format, ...) { - int len; - unsigned char *ptr; va_list ap; - va_start(ap, format); + int chars; + int lvl_code, sys_code; + + lvl_code = level&(~SYSLOG_SUBSYSTEM_MASK); + sys_code = level&SYSLOG_SUBSYSTEM_MASK; - if(logfindex >= MAX_LOGF_LINES) { - /* wrap */ - logfwrap = true; - logfindex = 0; + if (get_loglevel() < lvl_code) + return; /* too low, ignore it */ + else if (!(get_logsystems()&sys_code)) + return; /* not watching this sub-system */ + + if (MAX_LOGF_CHARS-log_start < 32) + logfdump(); + snprintf(&logfbuffer[log_start],6,"[%c%c] ",lvl_codes[lvl_code],lvl_codes[lvl_code]); + log_start+=5; + va_start(ap, format); + chars = vsnprintf(&logfbuffer[log_start], MAX_LOGF_CHARS-log_start, format, ap); + if (chars == (MAX_LOGF_CHARS-log_start)) /*likely it didnt get the whole error msg, so do it again */ + { + logfbuffer[log_start-5] = '\0'; + logfdump(); + snprintf(&logfbuffer[log_start],6,"[%c%c] ",lvl_codes[lvl_code],lvl_codes[lvl_code]); + log_start+=5; + chars = vsnprintf(&logfbuffer[log_start], MAX_LOGF_CHARS-log_start, format, ap); } - ptr = logfbuffer[logfindex]; - len = vsnprintf(ptr, MAX_LOGF_ENTRY, format, ap); va_end(ap); - if(len < MAX_LOGF_ENTRY) - /* pad with spaces up to the MAX_LOGF_ENTRY byte border */ - memset(ptr+len, ' ', MAX_LOGF_ENTRY-len); - - logfindex++; /* leave it where we write the next time */ + logfbuffer[log_start] = '\n'; + logfbuffer[log_start+1] = '\0'; + log_start += chars+1; +} - displayremote(); +void logf(const char *format, ...) +{ + va_list ap; + va_start(ap, format); + syslogf(SYSLOG_EVERYTHING , format, ap); + va_end(ap); } -#endif +bool logfdump(void) +{ + int fd = open(SYSLOG_FILE, O_CREAT|O_APPEND ); + if (fd < 0) + return false; /* no point doing any error messages here.. */ + + fdprintf(fd,"%s",logfbuffer); + log_start = 0; + close(fd); + return true; +} +char* get_next_log_msg(char* last_msg, char* buffer, int buf_size) +{ + char *s, *e; + if (last_msg == NULL) + s = logfbuffer; + else s = last_msg; + + if (s >= &logfbuffer[log_start]) + return NULL; + + e = strchr(s,'\n'); + if (e) + { + strncpy(buffer,s,(buf_size>(e-s))?e-s:buf_size); + return e + 1; + } + return NULL; +} Index: firmware/export/logf.h =================================================================== RCS file: /cvsroot/rockbox/firmware/export/logf.h,v retrieving revision 1.7 diff -u -r1.7 logf.h --- firmware/export/logf.h 30 Jun 2005 15:33:43 -0000 1.7 +++ firmware/export/logf.h 3 Jun 2006 13:39:38 -0000 @@ -21,20 +21,46 @@ #include #include -#ifdef ROCKBOX_HAS_LOGF - -#define MAX_LOGF_LINES 1000 -#define MAX_LOGF_ENTRY 30 -#define MAX_LOGF_DATASIZE (MAX_LOGF_ENTRY*MAX_LOGF_LINES) - -extern unsigned char logfbuffer[MAX_LOGF_LINES][MAX_LOGF_ENTRY]; -extern int logfindex; -extern bool logfwrap; +#define MAX_LOGF_CHARS 0x4000 /* 16k */ +#define SYSLOG_FILE "/.rockbox/syslog.log" +void init_logf(void); +void syslogf(const short int level, const char *format, ...); void logf(const char *format, ...); -#else -/* built without logf() support enabled */ -#define logf(...) -#endif +bool logfdump(void); +char* get_next_log_msg(char* last_msg, char* buffer, int buf_size); +extern short int log_level; + +#define set_log_level(a) log_level = a +#define get_log_level() log_level +#define get_loglevel() (log_level&(~SYSLOG_SUBSYSTEM_MASK)) +#define get_logsystems() (log_level&(SYSLOG_SUBSYSTEM_MASK)) + +/* syslog warning/error levels */ +/* level for syslog is a ( SYSLOG_LVL_* | SYSLOG_SYS_* ) or SYSLOG_EVERYTHING */ +/* BITS: ... UUUU USSS SSSS SLLL <- U: unused, S: sub-system L: level */ +/* If you add to these you need to change debug_menu.c also (down the very bottom */ +#define SYSLOG_LVL_INFO 0x0000 +#define SYSLOG_LVL_ATTENTION 0x0001 +#define SYSLOG_LVL_NOTICE 0x0002 +#define SYSLOG_LVL_WARNING 0x0003 +#define SYSLOG_LVL_ERROR 0x0004 +#define SYSLOG_LVL_URGENT 0x0005 +#define SYSLOG_LVL_CRITICAL 0x0006 +#define SYSLOG_LVL_NONE 0x0007 +static const char lvl_codes[8] = "IANIEUC"; + +#define SYSLOG_SYS_MAIN_THREAD 0x0008 +#define SYSLOG_SYS_PLAYBACK 0x0010 +#define SYSLOG_SYS_LCD 0x0020 +#define SYSLOG_SYS_PLUGIN 0x0040 +#define SYSLOG_SYS_CODEC 0x0080 +#define SYSLOG_SYS_POWER 0x0100 +#define SYSLOG_SYS_OTHER 0x0200 + +#define SYSLOG_EVERYTHING 0xFFFE /* every system, level CRITICAL */ +#define SYSLOG_SUBSYSTEM_MASK 0xFFF8 + + #endif /* LOGF_H */