1 /**
2  * @file lv_log.c
3  *
4  */
5 
6 /*********************
7  *      INCLUDES
8  *********************/
9 #include "lv_log.h"
10 #if LV_USE_LOG
11 
12 #include <stdarg.h>
13 #include <string.h>
14 #include "lv_printf.h"
15 #include "../hal/lv_hal_tick.h"
16 
17 #if LV_LOG_PRINTF
18     #include <stdio.h>
19 #endif
20 
21 /*********************
22  *      DEFINES
23  *********************/
24 
25 /**********************
26  *      TYPEDEFS
27  **********************/
28 
29 /**********************
30  *  STATIC PROTOTYPES
31  **********************/
32 
33 /**********************
34  *  STATIC VARIABLES
35  **********************/
36 static lv_log_print_g_cb_t custom_print_cb;
37 
38 /**********************
39  *      MACROS
40  **********************/
41 
42 /**********************
43  *   GLOBAL FUNCTIONS
44  **********************/
45 
46 /**
47  * Register custom print/write function to call when a log is added.
48  * It can format its "File path", "Line number" and "Description" as required
49  * and send the formatted log message to a console or serial port.
50  * @param print_cb a function pointer to print a log
51  */
lv_log_register_print_cb(lv_log_print_g_cb_t print_cb)52 void lv_log_register_print_cb(lv_log_print_g_cb_t print_cb)
53 {
54     custom_print_cb = print_cb;
55 }
56 
57 /**
58  * Add a log
59  * @param level the level of log. (From `lv_log_level_t` enum)
60  * @param file name of the file when the log added
61  * @param line line number in the source code where the log added
62  * @param func name of the function when the log added
63  * @param format printf-like format string
64  * @param ... parameters for `format`
65  */
_lv_log_add(lv_log_level_t level,const char * file,int line,const char * func,const char * format,...)66 void _lv_log_add(lv_log_level_t level, const char * file, int line, const char * func, const char * format, ...)
67 {
68     if(level >= _LV_LOG_LEVEL_NUM) return; /*Invalid level*/
69 
70     static uint32_t last_log_time = 0;
71 
72     if(level >= LV_LOG_LEVEL) {
73         va_list args;
74         va_start(args, format);
75 
76         /*Use only the file name not the path*/
77         size_t p;
78         for(p = strlen(file); p > 0; p--) {
79             if(file[p] == '/' || file[p] == '\\') {
80                 p++;    /*Skip the slash*/
81                 break;
82             }
83         }
84 
85         uint32_t t = lv_tick_get();
86         static const char * lvl_prefix[] = {"Trace", "Info", "Warn", "Error", "User"};
87 
88 #if LV_LOG_PRINTF
89         printf("[%s]\t(%" LV_PRId32 ".%03" LV_PRId32 ", +%" LV_PRId32 ")\t %s: ",
90                lvl_prefix[level], t / 1000, t % 1000, t - last_log_time, func);
91         vprintf(format, args);
92         printf(" \t(in %s line #%d)\n", &file[p], line);
93 #else
94         if(custom_print_cb) {
95             char buf[512];
96 #if LV_SPRINTF_CUSTOM
97             char msg[256];
98             lv_vsnprintf(msg, sizeof(msg), format, args);
99             lv_snprintf(buf, sizeof(buf), "[%s]\t(%" LV_PRId32 ".%03" LV_PRId32 ", +%" LV_PRId32 ")\t %s: %s \t(in %s line #%d)\n",
100                         lvl_prefix[level], t / 1000, t % 1000, t - last_log_time, func, msg, &file[p], line);
101 #else
102             lv_vaformat_t vaf = {format, &args};
103             lv_snprintf(buf, sizeof(buf), "[%s]\t(%" LV_PRId32 ".%03" LV_PRId32 ", +%" LV_PRId32 ")\t %s: %pV \t(in %s line #%d)\n",
104                         lvl_prefix[level], t / 1000, t % 1000, t - last_log_time, func, (void *)&vaf, &file[p], line);
105 #endif
106             custom_print_cb(buf);
107         }
108 #endif
109 
110         last_log_time = t;
111         va_end(args);
112     }
113 }
114 
lv_log(const char * buf)115 void lv_log(const char * buf)
116 {
117 #if LV_LOG_PRINTF
118     puts(buf);
119 #endif
120     if(custom_print_cb) custom_print_cb(buf);
121 }
122 
123 /**********************
124  *   STATIC FUNCTIONS
125  **********************/
126 
127 #endif /*LV_USE_LOG*/
128