blob: bdc5ad9cc00becbb30836405fa55ba6a24b31361 [file] [log] [blame]
Daniel Stenbergb033f6c2005-05-23 22:47:42 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Daniel Stenberg
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
Daniel Stenbergb033f6c2005-05-23 22:47:42 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22/*
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +000023 * logf() logs entries in a circular buffer. Each logged string is null-terminated.
Maurus Cuelenaere4c793fe2008-12-31 17:01:00 +000024 *
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +000025 * When the length of log exceeds MAX_LOGF_SIZE bytes, the buffer wraps.
Maurus Cuelenaere4c793fe2008-12-31 17:01:00 +000026 *
Daniel Stenbergb033f6c2005-05-23 22:47:42 +000027 */
28
29#include <string.h>
30#include <stdio.h>
31#include <stdarg.h>
Daniel Stenbergb033f6c2005-05-23 22:47:42 +000032#include "config.h"
Thomas Martitz6ac64202010-05-06 22:17:34 +000033#include "system.h"
34#include "font.h"
Frank Gevaerts25e50ed2014-01-05 22:20:26 +010035#include "lcd.h"
Rafaël Carréd00b7e82012-01-07 19:54:47 +000036#ifdef HAVE_REMOTE_LCD
Daniel Stenberg9e9f58f2005-05-24 14:28:48 +000037#include "lcd-remote.h"
Rafaël Carréd00b7e82012-01-07 19:54:47 +000038#endif
Daniel Stenberg11bf87f2005-05-24 14:26:54 +000039#include "logf.h"
Linus Nielsen Feltzing00d21822006-10-12 20:22:16 +000040#include "serial.h"
Jeffrey Goodeb8a51ad2010-05-15 03:47:06 +000041#include "format.h"
Daniel Stenbergb033f6c2005-05-23 22:47:42 +000042
Frank Gevaerts776d0152008-03-02 20:45:33 +000043#ifdef HAVE_USBSTACK
44#include "usb_core.h"
45#include "usbstack/usb_serial.h"
46#endif
47
Michael Giacomellid46b0902012-07-03 21:45:29 -040048#ifdef ROCKBOX_HAS_LOGDISKF
49#include "logdiskf.h"
50#include "file.h"
51#include "rbpaths.h"
52#include "ata_idle_notify.h"
53
54unsigned char logdiskfbuffer[MAX_LOGDISKF_SIZE];
Thomas Jaroschcfbd9cb2015-01-11 18:02:43 +010055static int logdiskfindex;
Michael Giacomellid46b0902012-07-03 21:45:29 -040056#endif
57
Daniel Stenbergedc07922005-05-30 13:00:43 +000058/* Only provide all this if asked to */
59#ifdef ROCKBOX_HAS_LOGF
60
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +000061#ifndef __PCTOOL__
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +000062unsigned char logfbuffer[MAX_LOGF_SIZE];
Linus Nielsen Feltzing056effc2005-05-24 14:01:16 +000063int logfindex;
Daniel Stenbergb033f6c2005-05-23 22:47:42 +000064bool logfwrap;
Mihail Zenkove5998102016-03-31 11:33:11 +000065bool logfenabled = true;
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +000066#endif
Daniel Stenbergb033f6c2005-05-23 22:47:42 +000067
Daniel Stenberg11bf87f2005-05-24 14:26:54 +000068#ifdef HAVE_REMOTE_LCD
69static void displayremote(void)
70{
71 /* TODO: we should have a debug option that enables/disables this! */
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +000072 int w, h, i;
73 int fontnr;
74 int cur_x, cur_y, delta_y, delta_x;
75 struct font* font;
76 int nb_lines;
77 char buf[2];
78 /* Memorize the pointer to the beginning of the last ... lines
79 I assume delta_y >= 6 to avoid wasting memory and allocating memory dynamically
80 I hope there is no font with height < 6 ! */
81 const int NB_ENTRIES=LCD_REMOTE_HEIGHT / 6;
82 int line_start_ptr[NB_ENTRIES];
Michael Giacomellid46b0902012-07-03 21:45:29 -040083
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +000084 fontnr = lcd_getfont();
85 font = font_get(fontnr);
Michael Giacomellid46b0902012-07-03 21:45:29 -040086
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +000087 /* get the horizontal size of each line */
88 font_getstringsize("A", NULL, &delta_y, fontnr);
Michael Giacomellid46b0902012-07-03 21:45:29 -040089
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +000090 /* font too small ? */
91 if(delta_y < 6)
92 return;
93 /* nothing to print ? */
94 if(logfindex == 0 && !logfwrap)
95 return;
Michael Giacomellid46b0902012-07-03 21:45:29 -040096
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +000097 w = LCD_REMOTE_WIDTH;
98 h = LCD_REMOTE_HEIGHT;
99 nb_lines = 0;
Michael Giacomellid46b0902012-07-03 21:45:29 -0400100
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000101 if(logfwrap)
102 i = logfindex;
103 else
104 i = 0;
Michael Giacomellid46b0902012-07-03 21:45:29 -0400105
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000106 cur_x = 0;
Michael Giacomellid46b0902012-07-03 21:45:29 -0400107
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000108 line_start_ptr[0] = i;
Michael Giacomellid46b0902012-07-03 21:45:29 -0400109
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000110 do
111 {
112 if(logfbuffer[i] == '\0')
113 {
114 line_start_ptr[++nb_lines % NB_ENTRIES] = i+1;
115 cur_x = 0;
116 }
117 else
118 {
119 /* does character fit on this line ? */
120 delta_x = font_get_width(font, logfbuffer[i]);
Michael Giacomellid46b0902012-07-03 21:45:29 -0400121
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000122 if(cur_x + delta_x > w)
123 {
124 cur_x = 0;
125 line_start_ptr[++nb_lines % NB_ENTRIES] = i;
126 }
127 /* update pointer */
128 cur_x += delta_x;
129 }
130 i++;
131 if(i >= MAX_LOGF_SIZE)
132 i = 0;
133 } while(i != logfindex);
Michael Giacomellid46b0902012-07-03 21:45:29 -0400134
Daniel Stenberg11bf87f2005-05-24 14:26:54 +0000135 lcd_remote_clear_display();
Michael Giacomellid46b0902012-07-03 21:45:29 -0400136
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000137 i = line_start_ptr[ MAX(nb_lines - h / delta_y, 0) % NB_ENTRIES];
138 cur_x = 0;
139 cur_y = 0;
140 buf[1] = '\0';
Michael Giacomellid46b0902012-07-03 21:45:29 -0400141
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000142 do {
143 if(logfbuffer[i] == '\0')
144 {
145 cur_y += delta_y;
146 cur_x = 0;
147 }
148 else
149 {
150 /* does character fit on this line ? */
151 delta_x = font_get_width(font, logfbuffer[i]);
Michael Giacomellid46b0902012-07-03 21:45:29 -0400152
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000153 if(cur_x + delta_x > w)
154 {
155 cur_y += delta_y;
156 cur_x = 0;
157 }
Michael Giacomellid46b0902012-07-03 21:45:29 -0400158
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000159 buf[0] = logfbuffer[i];
160 lcd_remote_putsxy(cur_x, cur_y, buf);
161 cur_x += delta_x;
Daniel Stenberg11bf87f2005-05-24 14:26:54 +0000162 }
Michael Giacomellid46b0902012-07-03 21:45:29 -0400163
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000164 i++;
165 if(i >= MAX_LOGF_SIZE)
166 i = 0;
167 } while(i != logfindex);
Michael Giacomellid46b0902012-07-03 21:45:29 -0400168
169 lcd_remote_update();
Daniel Stenberg11bf87f2005-05-24 14:26:54 +0000170}
171#else
172#define displayremote()
173#endif
174
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000175#ifdef __PCTOOL__
176void _logf(const char *format, ...)
177{
178 char buf[1024];
179 va_list ap;
180 va_start(ap, format);
Michael Giacomellid46b0902012-07-03 21:45:29 -0400181
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000182 vsnprintf(buf, sizeof buf, format, ap);
183 printf("DEBUG: %s\n", buf);
184}
185#else
Frank Gevaerts7ae9c8d2009-02-07 19:59:51 +0000186static void check_logfindex(void)
187{
Michael Giacomellid46b0902012-07-03 21:45:29 -0400188 if(logfindex >= MAX_LOGF_SIZE)
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000189 {
Frank Gevaerts7ae9c8d2009-02-07 19:59:51 +0000190 /* wrap */
191 logfwrap = true;
192 logfindex = 0;
193 }
194}
195
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000196static int logf_push(void *userp, unsigned char c)
Daniel Stenbergb033f6c2005-05-23 22:47:42 +0000197{
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000198 (void)userp;
Michael Giacomellid46b0902012-07-03 21:45:29 -0400199
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000200 logfbuffer[logfindex++] = c;
201 check_logfindex();
Michael Giacomellid46b0902012-07-03 21:45:29 -0400202
Ralf Ertzingerd2f97da2011-09-09 12:28:36 +0200203#if defined(HAVE_SERIAL) && !defined(SIMULATOR) && defined(LOGF_SERIAL)
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000204 if(c != '\0')
205 {
206 char buf[2];
207 buf[0] = c;
208 buf[1] = '\0';
209 serial_tx(buf);
210 }
211#endif
Michael Giacomellid46b0902012-07-03 21:45:29 -0400212
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000213 return true;
214}
215
216void _logf(const char *fmt, ...)
217{
Mihail Zenkove5998102016-03-31 11:33:11 +0000218 if (!logfenabled)
219 return;
220
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000221 #ifdef USB_ENABLE_SERIAL
222 int old_logfindex = logfindex;
223 #endif
224 va_list ap;
225
226 va_start(ap, fmt);
Michael Giacomellid46b0902012-07-03 21:45:29 -0400227
Thomas Martitz35e8b142010-06-21 16:53:00 +0000228#if (CONFIG_PLATFORM & PLATFORM_HOSTED)
Jeffrey Goodefade88a2009-11-02 15:30:06 +0000229 char buf[1024];
230 vsnprintf(buf, sizeof buf, fmt, ap);
231 DEBUGF("%s\n", buf);
Amaury Poulyc0838062010-08-02 09:10:35 +0000232 /* restart va_list otherwise the result if undefined when vuprintf is called */
233 va_end(ap);
234 va_start(ap, fmt);
Jeffrey Goodefade88a2009-11-02 15:30:06 +0000235#endif
236
Thomas Martitz1ddb91a2009-11-03 21:20:09 +0000237 vuprintf(logf_push, NULL, fmt, ap);
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000238 va_end(ap);
Michael Giacomellid46b0902012-07-03 21:45:29 -0400239
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000240 /* add trailing zero */
241 logf_push(NULL, '\0');
Michael Giacomellid46b0902012-07-03 21:45:29 -0400242
Ralf Ertzingerd2f97da2011-09-09 12:28:36 +0200243#if defined(HAVE_SERIAL) && !defined(SIMULATOR) && defined(LOGF_SERIAL)
Linus Nielsen Feltzing00d21822006-10-12 20:22:16 +0000244 serial_tx("\r\n");
245#endif
Frank Gevaertsc61a7512009-05-23 14:30:20 +0000246#ifdef USB_ENABLE_SERIAL
Frank Gevaerts776d0152008-03-02 20:45:33 +0000247
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000248 if(logfindex < old_logfindex)
Maurus Cuelenaere4c793fe2008-12-31 17:01:00 +0000249 {
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000250 usb_serial_send(logfbuffer + old_logfindex, MAX_LOGF_SIZE - old_logfindex);
251 usb_serial_send(logfbuffer, logfindex - 1);
Maurus Cuelenaere4c793fe2008-12-31 17:01:00 +0000252 }
Maurus Cuelenaere20b0dd22009-08-21 22:54:23 +0000253 else
254 usb_serial_send(logfbuffer + old_logfindex, logfindex - old_logfindex - 1);
255 usb_serial_send("\r\n", 2);
Michael Giacomellid46b0902012-07-03 21:45:29 -0400256#endif
Daniel Stenberg11bf87f2005-05-24 14:26:54 +0000257
258 displayremote();
Daniel Stenbergb033f6c2005-05-23 22:47:42 +0000259}
Miika Pekkarinen0dd7ea22006-11-10 08:03:33 +0000260#endif
Daniel Stenbergedc07922005-05-30 13:00:43 +0000261
Frank Gevaerts25e50ed2014-01-05 22:20:26 +0100262void logf_panic_dump(int *y)
263{
264 int i;
265 /* nothing to print ? */
266 if(logfindex == 0 && !logfwrap)
267 {
268 lcd_puts(1, (*y)++, "no logf data");
269 lcd_update();
270 return;
271 }
272
273 lcd_puts(1, (*y)++, "start of logf data");
274 lcd_update();
275 i = logfindex - 2; /* The last actual characer (i.e. not '\0') */
276
277 while(i >= 0)
278 {
279 while(logfbuffer[i] != 0 && i>=0)
280 {
281 i--;
282 }
283 if(strlen( &logfbuffer[i + 1]) > 0)
284 {
285 lcd_puts(1, (*y)++, &logfbuffer[i + 1]);
286 lcd_update();
287 }
288 i--;
289 }
290 if(logfwrap)
291 {
292 i = MAX_LOGF_SIZE - 1;
293 while(i >= logfindex)
294 {
295 while(logfbuffer[i] != 0 && i >= logfindex)
296 {
297 i--;
298 }
299 if(strlen( &logfbuffer[i + 1]) > 0)
300 {
301 lcd_putsf(1, (*y)++, "%*s", (MAX_LOGF_SIZE-i) &logfbuffer[i + 1]);
302 lcd_update();
303 }
304 }
305 i--;
306 }
307 lcd_puts(1, (*y)++, "end of logf data");
308 lcd_update();
309}
Daniel Stenbergedc07922005-05-30 13:00:43 +0000310#endif
Michael Giacomellid46b0902012-07-03 21:45:29 -0400311
312#ifdef ROCKBOX_HAS_LOGDISKF
313static int logdiskf_push(void *userp, unsigned char c)
314{
315 (void)userp;
316
317 /*just stop logging if out of space*/
318 if(logdiskfindex>=MAX_LOGDISKF_SIZE-1)
319 {
320 strcpy(&logdiskfbuffer[logdiskfindex-8], "LOGFULL");
321 logdiskfindex=MAX_LOGDISKF_SIZE;
322 return false;
323 }
324 logdiskfbuffer[logdiskfindex++] = c;
325
326 return true;
327}
328
Thomas Martitz470989b2014-03-14 23:15:16 +0100329static void flush_buffer(void);
Amaury Poulyc13f21a2013-08-16 21:55:09 +0200330
Michael Giacomellid46b0902012-07-03 21:45:29 -0400331void _logdiskf(const char* file, const char level, const char *fmt, ...)
332{
333
334 va_list ap;
335
336 va_start(ap, fmt);
337 int len =strlen(file);
338 if(logdiskfindex +len + 4 > MAX_LOGDISKF_SIZE-1)
339 {
340 strcpy(&logdiskfbuffer[logdiskfindex-8], "LOGFULL");
341 logdiskfindex=MAX_LOGDISKF_SIZE;
Thomas Jaroschef1497c2014-12-20 13:47:28 +0100342 va_end(ap);
Michael Giacomellid46b0902012-07-03 21:45:29 -0400343 return;
344 }
345
346 logdiskf_push(NULL, level);
347 logdiskf_push(NULL, ' ');
348 logdiskf_push(NULL, '[');
349 strcpy(&logdiskfbuffer[logdiskfindex], file);
350 logdiskfindex += len;
351 logdiskf_push(NULL, ']');
352
353 vuprintf(logdiskf_push, NULL, fmt, ap);
354 va_end(ap);
Amaury Poulyc13f21a2013-08-16 21:55:09 +0200355 register_storage_idle_func(flush_buffer);
Michael Giacomellid46b0902012-07-03 21:45:29 -0400356}
Amaury Poulyc13f21a2013-08-16 21:55:09 +0200357
Thomas Martitz470989b2014-03-14 23:15:16 +0100358static void flush_buffer(void)
Michael Giacomellid46b0902012-07-03 21:45:29 -0400359{
Michael Giacomellid46b0902012-07-03 21:45:29 -0400360 int fd;
361 if(logdiskfindex < 1)
362 return;
363
364 fd = open(HOME_DIR"/rockbox_log.txt", O_RDWR | O_CREAT | O_APPEND, 0666);
365 if (fd < 0)
366 return;
367
368 write(fd, logdiskfbuffer, logdiskfindex);
369 close(fd);
370
371 logdiskfindex = 0;
372}
373
Michael Giacomelli633dd492012-08-06 19:18:20 -0400374#endif