diff options
author | Michael Giacomelli <giac2000@hotmail.com> | 2012-07-03 21:45:29 -0400 |
---|---|---|
committer | Michael Giacomelli <mgiacomelli@gmail.com> | 2012-08-07 00:53:46 +0200 |
commit | d46b090771291c10127d0fb421ee3c9f1e8f69b1 (patch) | |
tree | ae5a6e01f6d2025294f8905a9a791c4ede3d4869 /firmware/logf.c | |
parent | 7c31ff2fb0cc3ba40f82c3b02daf1e7ca41e1cf6 (diff) | |
download | rockbox-d46b090771291c10127d0fb421ee3c9f1e8f69b1.tar.gz rockbox-d46b090771291c10127d0fb421ee3c9f1e8f69b1.zip |
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 <rockbox@jdgordon.info>
Tested-by: Michael Giacomelli <mgiacomelli@gmail.com>
Reviewed-by: Michael Giacomelli <mgiacomelli@gmail.com>
Diffstat (limited to 'firmware/logf.c')
-rw-r--r-- | firmware/logf.c | 129 |
1 files changed, 103 insertions, 26 deletions
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 @@ | |||
44 | #include "usbstack/usb_serial.h" | 44 | #include "usbstack/usb_serial.h" |
45 | #endif | 45 | #endif |
46 | 46 | ||
47 | #ifdef ROCKBOX_HAS_LOGDISKF | ||
48 | #include "logdiskf.h" | ||
49 | #include "file.h" | ||
50 | #include "rbpaths.h" | ||
51 | #include "ata_idle_notify.h" | ||
52 | |||
53 | unsigned char logdiskfbuffer[MAX_LOGDISKF_SIZE]; | ||
54 | int logdiskfindex; | ||
55 | #endif | ||
56 | |||
47 | /* Only provide all this if asked to */ | 57 | /* Only provide all this if asked to */ |
48 | #ifdef ROCKBOX_HAS_LOGF | 58 | #ifdef ROCKBOX_HAS_LOGF |
49 | 59 | ||
@@ -68,33 +78,33 @@ static void displayremote(void) | |||
68 | I hope there is no font with height < 6 ! */ | 78 | I hope there is no font with height < 6 ! */ |
69 | const int NB_ENTRIES=LCD_REMOTE_HEIGHT / 6; | 79 | const int NB_ENTRIES=LCD_REMOTE_HEIGHT / 6; |
70 | int line_start_ptr[NB_ENTRIES]; | 80 | int line_start_ptr[NB_ENTRIES]; |
71 | 81 | ||
72 | fontnr = lcd_getfont(); | 82 | fontnr = lcd_getfont(); |
73 | font = font_get(fontnr); | 83 | font = font_get(fontnr); |
74 | 84 | ||
75 | /* get the horizontal size of each line */ | 85 | /* get the horizontal size of each line */ |
76 | font_getstringsize("A", NULL, &delta_y, fontnr); | 86 | font_getstringsize("A", NULL, &delta_y, fontnr); |
77 | 87 | ||
78 | /* font too small ? */ | 88 | /* font too small ? */ |
79 | if(delta_y < 6) | 89 | if(delta_y < 6) |
80 | return; | 90 | return; |
81 | /* nothing to print ? */ | 91 | /* nothing to print ? */ |
82 | if(logfindex == 0 && !logfwrap) | 92 | if(logfindex == 0 && !logfwrap) |
83 | return; | 93 | return; |
84 | 94 | ||
85 | w = LCD_REMOTE_WIDTH; | 95 | w = LCD_REMOTE_WIDTH; |
86 | h = LCD_REMOTE_HEIGHT; | 96 | h = LCD_REMOTE_HEIGHT; |
87 | nb_lines = 0; | 97 | nb_lines = 0; |
88 | 98 | ||
89 | if(logfwrap) | 99 | if(logfwrap) |
90 | i = logfindex; | 100 | i = logfindex; |
91 | else | 101 | else |
92 | i = 0; | 102 | i = 0; |
93 | 103 | ||
94 | cur_x = 0; | 104 | cur_x = 0; |
95 | 105 | ||
96 | line_start_ptr[0] = i; | 106 | line_start_ptr[0] = i; |
97 | 107 | ||
98 | do | 108 | do |
99 | { | 109 | { |
100 | if(logfbuffer[i] == '\0') | 110 | if(logfbuffer[i] == '\0') |
@@ -106,7 +116,7 @@ static void displayremote(void) | |||
106 | { | 116 | { |
107 | /* does character fit on this line ? */ | 117 | /* does character fit on this line ? */ |
108 | delta_x = font_get_width(font, logfbuffer[i]); | 118 | delta_x = font_get_width(font, logfbuffer[i]); |
109 | 119 | ||
110 | if(cur_x + delta_x > w) | 120 | if(cur_x + delta_x > w) |
111 | { | 121 | { |
112 | cur_x = 0; | 122 | cur_x = 0; |
@@ -119,14 +129,14 @@ static void displayremote(void) | |||
119 | if(i >= MAX_LOGF_SIZE) | 129 | if(i >= MAX_LOGF_SIZE) |
120 | i = 0; | 130 | i = 0; |
121 | } while(i != logfindex); | 131 | } while(i != logfindex); |
122 | 132 | ||
123 | lcd_remote_clear_display(); | 133 | lcd_remote_clear_display(); |
124 | 134 | ||
125 | i = line_start_ptr[ MAX(nb_lines - h / delta_y, 0) % NB_ENTRIES]; | 135 | i = line_start_ptr[ MAX(nb_lines - h / delta_y, 0) % NB_ENTRIES]; |
126 | cur_x = 0; | 136 | cur_x = 0; |
127 | cur_y = 0; | 137 | cur_y = 0; |
128 | buf[1] = '\0'; | 138 | buf[1] = '\0'; |
129 | 139 | ||
130 | do { | 140 | do { |
131 | if(logfbuffer[i] == '\0') | 141 | if(logfbuffer[i] == '\0') |
132 | { | 142 | { |
@@ -137,24 +147,24 @@ static void displayremote(void) | |||
137 | { | 147 | { |
138 | /* does character fit on this line ? */ | 148 | /* does character fit on this line ? */ |
139 | delta_x = font_get_width(font, logfbuffer[i]); | 149 | delta_x = font_get_width(font, logfbuffer[i]); |
140 | 150 | ||
141 | if(cur_x + delta_x > w) | 151 | if(cur_x + delta_x > w) |
142 | { | 152 | { |
143 | cur_y += delta_y; | 153 | cur_y += delta_y; |
144 | cur_x = 0; | 154 | cur_x = 0; |
145 | } | 155 | } |
146 | 156 | ||
147 | buf[0] = logfbuffer[i]; | 157 | buf[0] = logfbuffer[i]; |
148 | lcd_remote_putsxy(cur_x, cur_y, buf); | 158 | lcd_remote_putsxy(cur_x, cur_y, buf); |
149 | cur_x += delta_x; | 159 | cur_x += delta_x; |
150 | } | 160 | } |
151 | 161 | ||
152 | i++; | 162 | i++; |
153 | if(i >= MAX_LOGF_SIZE) | 163 | if(i >= MAX_LOGF_SIZE) |
154 | i = 0; | 164 | i = 0; |
155 | } while(i != logfindex); | 165 | } while(i != logfindex); |
156 | 166 | ||
157 | lcd_remote_update(); | 167 | lcd_remote_update(); |
158 | } | 168 | } |
159 | #else | 169 | #else |
160 | #define displayremote() | 170 | #define displayremote() |
@@ -166,14 +176,14 @@ void _logf(const char *format, ...) | |||
166 | char buf[1024]; | 176 | char buf[1024]; |
167 | va_list ap; | 177 | va_list ap; |
168 | va_start(ap, format); | 178 | va_start(ap, format); |
169 | 179 | ||
170 | vsnprintf(buf, sizeof buf, format, ap); | 180 | vsnprintf(buf, sizeof buf, format, ap); |
171 | printf("DEBUG: %s\n", buf); | 181 | printf("DEBUG: %s\n", buf); |
172 | } | 182 | } |
173 | #else | 183 | #else |
174 | static void check_logfindex(void) | 184 | static void check_logfindex(void) |
175 | { | 185 | { |
176 | if(logfindex >= MAX_LOGF_SIZE) | 186 | if(logfindex >= MAX_LOGF_SIZE) |
177 | { | 187 | { |
178 | /* wrap */ | 188 | /* wrap */ |
179 | logfwrap = true; | 189 | logfwrap = true; |
@@ -184,10 +194,10 @@ static void check_logfindex(void) | |||
184 | static int logf_push(void *userp, unsigned char c) | 194 | static int logf_push(void *userp, unsigned char c) |
185 | { | 195 | { |
186 | (void)userp; | 196 | (void)userp; |
187 | 197 | ||
188 | logfbuffer[logfindex++] = c; | 198 | logfbuffer[logfindex++] = c; |
189 | check_logfindex(); | 199 | check_logfindex(); |
190 | 200 | ||
191 | #if defined(HAVE_SERIAL) && !defined(SIMULATOR) && defined(LOGF_SERIAL) | 201 | #if defined(HAVE_SERIAL) && !defined(SIMULATOR) && defined(LOGF_SERIAL) |
192 | if(c != '\0') | 202 | if(c != '\0') |
193 | { | 203 | { |
@@ -197,7 +207,7 @@ static int logf_push(void *userp, unsigned char c) | |||
197 | serial_tx(buf); | 207 | serial_tx(buf); |
198 | } | 208 | } |
199 | #endif | 209 | #endif |
200 | 210 | ||
201 | return true; | 211 | return true; |
202 | } | 212 | } |
203 | 213 | ||
@@ -209,7 +219,7 @@ void _logf(const char *fmt, ...) | |||
209 | va_list ap; | 219 | va_list ap; |
210 | 220 | ||
211 | va_start(ap, fmt); | 221 | va_start(ap, fmt); |
212 | 222 | ||
213 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) | 223 | #if (CONFIG_PLATFORM & PLATFORM_HOSTED) |
214 | char buf[1024]; | 224 | char buf[1024]; |
215 | vsnprintf(buf, sizeof buf, fmt, ap); | 225 | vsnprintf(buf, sizeof buf, fmt, ap); |
@@ -221,10 +231,10 @@ void _logf(const char *fmt, ...) | |||
221 | 231 | ||
222 | vuprintf(logf_push, NULL, fmt, ap); | 232 | vuprintf(logf_push, NULL, fmt, ap); |
223 | va_end(ap); | 233 | va_end(ap); |
224 | 234 | ||
225 | /* add trailing zero */ | 235 | /* add trailing zero */ |
226 | logf_push(NULL, '\0'); | 236 | logf_push(NULL, '\0'); |
227 | 237 | ||
228 | #if defined(HAVE_SERIAL) && !defined(SIMULATOR) && defined(LOGF_SERIAL) | 238 | #if defined(HAVE_SERIAL) && !defined(SIMULATOR) && defined(LOGF_SERIAL) |
229 | serial_tx("\r\n"); | 239 | serial_tx("\r\n"); |
230 | #endif | 240 | #endif |
@@ -238,10 +248,77 @@ void _logf(const char *fmt, ...) | |||
238 | else | 248 | else |
239 | usb_serial_send(logfbuffer + old_logfindex, logfindex - old_logfindex - 1); | 249 | usb_serial_send(logfbuffer + old_logfindex, logfindex - old_logfindex - 1); |
240 | usb_serial_send("\r\n", 2); | 250 | usb_serial_send("\r\n", 2); |
241 | #endif | 251 | #endif |
242 | 252 | ||
243 | displayremote(); | 253 | displayremote(); |
244 | } | 254 | } |
245 | #endif | 255 | #endif |
246 | 256 | ||
247 | #endif | 257 | #endif |
258 | |||
259 | #ifdef ROCKBOX_HAS_LOGDISKF | ||
260 | static int logdiskf_push(void *userp, unsigned char c) | ||
261 | { | ||
262 | (void)userp; | ||
263 | |||
264 | /*just stop logging if out of space*/ | ||
265 | if(logdiskfindex>=MAX_LOGDISKF_SIZE-1) | ||
266 | { | ||
267 | strcpy(&logdiskfbuffer[logdiskfindex-8], "LOGFULL"); | ||
268 | logdiskfindex=MAX_LOGDISKF_SIZE; | ||
269 | return false; | ||
270 | } | ||
271 | logdiskfbuffer[logdiskfindex++] = c; | ||
272 | |||
273 | return true; | ||
274 | } | ||
275 | |||
276 | void _logdiskf(const char* file, const char level, const char *fmt, ...) | ||
277 | { | ||
278 | |||
279 | va_list ap; | ||
280 | |||
281 | va_start(ap, fmt); | ||
282 | int len =strlen(file); | ||
283 | if(logdiskfindex +len + 4 > MAX_LOGDISKF_SIZE-1) | ||
284 | { | ||
285 | strcpy(&logdiskfbuffer[logdiskfindex-8], "LOGFULL"); | ||
286 | logdiskfindex=MAX_LOGDISKF_SIZE; | ||
287 | return; | ||
288 | } | ||
289 | |||
290 | logdiskf_push(NULL, level); | ||
291 | logdiskf_push(NULL, ' '); | ||
292 | logdiskf_push(NULL, '['); | ||
293 | strcpy(&logdiskfbuffer[logdiskfindex], file); | ||
294 | logdiskfindex += len; | ||
295 | logdiskf_push(NULL, ']'); | ||
296 | |||
297 | vuprintf(logdiskf_push, NULL, fmt, ap); | ||
298 | va_end(ap); | ||
299 | |||
300 | |||
301 | } | ||
302 | static void flush_buffer(void* data) | ||
303 | { | ||
304 | (void)data; | ||
305 | int fd; | ||
306 | if(logdiskfindex < 1) | ||
307 | return; | ||
308 | |||
309 | fd = open(HOME_DIR"/rockbox_log.txt", O_RDWR | O_CREAT | O_APPEND, 0666); | ||
310 | if (fd < 0) | ||
311 | return; | ||
312 | |||
313 | write(fd, logdiskfbuffer, logdiskfindex); | ||
314 | close(fd); | ||
315 | |||
316 | logdiskfindex = 0; | ||
317 | } | ||
318 | |||
319 | void init_logdiskf() | ||
320 | { | ||
321 | register_storage_idle_func(flush_buffer); | ||
322 | } | ||
323 | |||
324 | #endif \ No newline at end of file | ||