1 /*
2 Copyright (c) 2012, Broadcom Europe Ltd
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are met:
7     * Redistributions of source code must retain the above copyright
8       notice, this list of conditions and the following disclaimer.
9     * Redistributions in binary form must reproduce the above copyright
10       notice, this list of conditions and the following disclaimer in the
11       documentation and/or other materials provided with the distribution.
12     * Neither the name of the copyright holder nor the
13       names of its contributors may be used to endorse or promote products
14       derived from this software without specific prior written permission.
15 
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
20 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27 
28 /*=============================================================================
29 VideoCore OS Abstraction Layer - logging support
30 =============================================================================*/
31 
32 #ifndef VCOS_LOGGING_H
33 #define VCOS_LOGGING_H
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 #include <stdarg.h>
40 
41 #include "interface/vcos/vcos_types.h"
42 #include "vcos.h"
43 #include "vcos_logging_control.h"
44 
45 /**
46  * \file
47  *
48  * Logging support
49  *
50  * This provides categorised logging. Clients register
51  * a category, and then get a number of logging levels for
52  * that category.
53  *
54  * The logging level flag is tested using a flag *before* the
55  * function call, which makes logging very fast when disabled - there
56  * is no function call overhead just to find out that this log
57  * message is disabled.
58  *
59  * \section VCOS_LOG_CATEGORY
60  *
61  * As a convenience, clients define VCOS_LOG_CATEGORY to point to
62  * their category; the various vcos_log_xxx() macros then expand to
63  * use this.
64  *
65  * e.g.
66  *
67  *     #define VCOS_LOG_CATEGORY (&my_category)
68  *
69  *     #include <interface/vcos/vcos.h>
70  *
71  *     VCOS_LOG_CAT_T my_category;
72  *
73  *     ....
74  *
75  *     vcos_log_trace("Stuff happened: %d", n_stuff);
76  *
77  */
78 
79 /** Logging levels */
80 typedef enum VCOS_LOG_LEVEL_T
81 {
82    VCOS_LOG_UNINITIALIZED   = 0,
83    VCOS_LOG_NEVER,
84    VCOS_LOG_ERROR,
85    VCOS_LOG_WARN,
86    VCOS_LOG_INFO,
87    VCOS_LOG_TRACE,
88 } VCOS_LOG_LEVEL_T;
89 
90 
91 /** Initialize a logging category without going through vcos_log_register().
92  *
93  * This is useful for the case where there is no obvious point to do the
94  * registration (no initialization function for the module). However, it
95  * means that your logging category is not registered, so cannot be easily
96  * changed at run-time.
97  */
98 #define VCOS_LOG_INIT(n,l) { l, n, 0, {0}, 0, 0 }
99 
100 /** A registered logging category.
101   */
102 typedef struct VCOS_LOG_CAT_T
103 {
104    VCOS_LOG_LEVEL_T level;      /**< Which levels are enabled for this category */
105    const char *name;            /**< Name for this category. */
106    struct VCOS_LOG_CAT_T *next;
107    struct {
108       unsigned int want_prefix:1;
109    } flags;
110    unsigned int refcount;
111    void *platform_data;         /**< platform specific data */
112 } VCOS_LOG_CAT_T;
113 
114 typedef void (*VCOS_VLOG_IMPL_FUNC_T)(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args);
115 
116 /** Convert a VCOS_LOG_LEVEL_T into a printable string.
117   * The platform needs to implement this function.
118   */
119 VCOSPRE_ const char * VCOSPOST_ vcos_log_level_to_string( VCOS_LOG_LEVEL_T level );
120 
121 /** Convert a string into a VCOS_LOG_LEVEL_T
122   * The platform needs to implement this function.
123   */
124 VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_string_to_log_level( const char *str, VCOS_LOG_LEVEL_T *level );
125 
126 /** Log a message. Basic API. Normal code should not use this.
127   * The platform needs to implement this function.
128   */
129 VCOSPRE_ void VCOSPOST_ vcos_log_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, ...) VCOS_FORMAT_ATTR_(printf, 3, 4);
130 
131 /** Log a message using a varargs parameter list. Normal code should
132   * not use this.
133   */
134 VCOSPRE_ void VCOSPOST_ vcos_vlog_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args) VCOS_FORMAT_ATTR_(printf, 3, 0);
135 
136 /** Set the function which does the actual logging output.
137  *  Passing in NULL causes the default logging function to be
138  *  used.
139   */
140 VCOSPRE_ void VCOSPOST_ vcos_set_vlog_impl( VCOS_VLOG_IMPL_FUNC_T vlog_impl_func );
141 
142 /** The default logging function, which is provided by each
143   * platform.
144   */
145 
146 VCOSPRE_ void VCOSPOST_ vcos_vlog_default_impl(const VCOS_LOG_CAT_T *cat, VCOS_LOG_LEVEL_T _level, const char *fmt, va_list args) VCOS_FORMAT_ATTR_(printf, 3, 0);
147 
148 /*
149  * Initialise the logging subsystem. This is called from
150  * vcos_init() so you don't normally need to call it.
151  */
152 VCOSPRE_ void VCOSPOST_ vcos_logging_init(void);
153 
154 /** Register a logging category.
155   *
156   * @param name the name of this category.
157   * @param category the category to register.
158   */
159 VCOSPRE_ void VCOSPOST_ vcos_log_register(const char *name, VCOS_LOG_CAT_T *category);
160 
161 /** Unregister a logging category.
162   */
163 VCOSPRE_ void VCOSPOST_ vcos_log_unregister(VCOS_LOG_CAT_T *category);
164 
165 /** Return a default logging category, for people too lazy to create their own.
166   *
167   * Using the default category will be slow (there's an extra function
168   * call overhead). Don't do this in normal code.
169   */
170 VCOSPRE_ const VCOS_LOG_CAT_T * VCOSPOST_ vcos_log_get_default_category(void);
171 
172 VCOSPRE_ void VCOSPOST_ vcos_set_log_options(const char *opt);
173 
174 /** Set the logging level for a category at run time. Without this, the level
175   * will be that set by vcos_log_register from a platform-specific source.
176   *
177   * @param category the category to modify.
178   * @param level the new logging level for this category.
179   */
vcos_log_set_level(VCOS_LOG_CAT_T * category,VCOS_LOG_LEVEL_T level)180 VCOS_STATIC_INLINE void vcos_log_set_level(VCOS_LOG_CAT_T *category, VCOS_LOG_LEVEL_T level)
181 {
182    category->level = level;
183 }
184 
185 
186 /** Set the logging levels for many categories at once.
187   *
188   * Set lots of categorys from a string cat:lev,cat:lev This can
189   * be used at startup time to set a bunch of category levels from
190   * a single string.  Used with C(vcos_logging_level)
191   */
192 VCOSPRE_ void VCOSPOST_ vcos_log_set_level_all(char *levels);
193 
194 #define vcos_log_dump_mem(cat,label,addr,voidMem,numBytes)  do { if (vcos_is_log_enabled(cat,VCOS_LOG_TRACE)) vcos_log_dump_mem_impl(cat,label,addr,voidMem,numBytes); } while (0)
195 
196 void vcos_log_dump_mem_impl( const VCOS_LOG_CAT_T *cat,
197                              const char           *label,
198                              uint32_t              addr,
199                              const void           *voidMem,
200                              size_t                numBytes );
201 
202 /*
203  * Platform specific hooks (optional).
204  */
205 #ifndef vcos_log_platform_init
206 #define vcos_log_platform_init()                (void)0
207 #endif
208 
209 #ifndef vcos_log_platform_register
210 #define vcos_log_platform_register(category)    (void)0
211 #endif
212 
213 #ifndef vcos_log_platform_unregister
214 #define vcos_log_platform_unregister(category)  (void)0
215 #endif
216 
217 /* VCOS_TRACE() - deprecated macro which just outputs in a debug build and
218  * is a no-op in a release build.
219  *
220  * _VCOS_LOG_X() - internal macro which outputs if the current level for the
221  * particular category is higher than the supplied message level.
222  */
223 
224 #define VCOS_LOG_DFLT_CATEGORY vcos_log_get_default_category()
225 
226 #define _VCOS_LEVEL(x) (x)
227 
228 #define vcos_is_log_enabled(cat,_level)  (_VCOS_LEVEL((cat)->level) >= _VCOS_LEVEL(_level))
229 
230 #if defined(_VCOS_METAWARE) || defined(__GNUC__)
231 
232 # if !defined(AMPUTATE_ALL_VCOS_LOGGING) && (!defined(NDEBUG) || defined(VCOS_ALWAYS_WANT_LOGGING))
233 #  define VCOS_LOGGING_ENABLED
234 #  define _VCOS_LOG_X(cat, _level, fmt...)   do { if (vcos_is_log_enabled(cat,_level)) vcos_log_impl(cat,_level,fmt); } while (0)
235 #  define _VCOS_VLOG_X(cat, _level, fmt, ap) do { if (vcos_is_log_enabled(cat,_level)) vcos_vlog_impl(cat,_level,fmt,ap); } while (0)
236 # else
237 #  define _VCOS_LOG_X(cat, _level, fmt...) (void)0
238 #  define _VCOS_VLOG_X(cat, _level, fmt, ap) (void)0
239 # endif
240 
241 
242 
243 # define vcos_log_error(...)   _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_ERROR, __VA_ARGS__)
244 # define vcos_log_warn(...)    _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_WARN, __VA_ARGS__)
245 # define vcos_log_info(...)    _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_INFO, __VA_ARGS__)
246 # define vcos_log_trace(...)   _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE, __VA_ARGS__)
247 
248 # define vcos_vlog_error(fmt,ap)  _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_ERROR, fmt, ap)
249 # define vcos_vlog_warn(fmt,ap)   _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_WARN, fmt, ap)
250 # define vcos_vlog_info(fmt,ap)   _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_INFO, fmt, ap)
251 # define vcos_vlog_trace(fmt,ap)  _VCOS_VLOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE, fmt, ap)
252 
253 # define vcos_logc_error(cat,...)   _VCOS_LOG_X(cat, VCOS_LOG_ERROR, __VA_ARGS__)
254 # define vcos_logc_warn(cat,...)    _VCOS_LOG_X(cat, VCOS_LOG_WARN, __VA_ARGS__)
255 # define vcos_logc_info(cat,...)    _VCOS_LOG_X(cat, VCOS_LOG_INFO, __VA_ARGS__)
256 # define vcos_logc_trace(cat,...)   _VCOS_LOG_X(cat, VCOS_LOG_TRACE, __VA_ARGS__)
257 
258 # define vcos_vlogc_error(cat,fmt,ap)  _VCOS_VLOG_X(cat, VCOS_LOG_ERROR, fmt, ap)
259 # define vcos_vlogc_warn(cat,fmt,ap)   _VCOS_VLOG_X(cat, VCOS_LOG_WARN, fmt, ap)
260 # define vcos_vlogc_info(cat,fmt,ap)   _VCOS_VLOG_X(cat, VCOS_LOG_INFO, fmt, ap)
261 # define vcos_vlogc_trace(cat,fmt,ap)  _VCOS_VLOG_X(cat, VCOS_LOG_TRACE, fmt, ap)
262 
263 # define vcos_log(...)   _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, __VA_ARGS__)
264 # define vcos_vlog(fmt,ap)  _VCOS_VLOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, fmt, ap)
265 # define VCOS_ALERT(...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_ERROR, __VA_ARGS__)
266 # define VCOS_TRACE(...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, __VA_ARGS__)
267 
268 /*
269  * MS Visual Studio - pre 2005 does not grok variadic macros
270  */
271 #elif defined(_MSC_VER)
272 
273 # if _MSC_VER >= 1400
274 
275 #  if !defined(AMPUTATE_ALL_VCOS_LOGGING) && (!defined(NDEBUG) || defined(VCOS_ALWAYS_WANT_LOGGING))
276 #   define VCOS_LOGGING_ENABLED
277 #   define _VCOS_LOG_X(cat, _level, fmt,...) do { if (vcos_is_log_enabled(cat,_level)) vcos_log_impl(cat, _level, fmt, __VA_ARGS__); } while (0)
278 #  else
279 #   define _VCOS_LOG_X(cat, _level, fmt,...) (void)0
280 #  endif
281 
282 # define vcos_log_error(fmt,...)   _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_ERROR, fmt, __VA_ARGS__)
283 # define vcos_log_warn(fmt,...)    _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_WARN, fmt, __VA_ARGS__)
284 # define vcos_log_info(fmt,...)    _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_INFO, fmt, __VA_ARGS__)
285 # define vcos_log_trace(fmt,...)   _VCOS_LOG_X(VCOS_LOG_CATEGORY, VCOS_LOG_TRACE, fmt, __VA_ARGS__)
286 
287 # define vcos_logc_error(cat,fmt,...)   _VCOS_LOG_X(cat, VCOS_LOG_ERROR, fmt, __VA_ARGS__)
288 # define vcos_logc_warn(cat,fmt,...)    _VCOS_LOG_X(cat, VCOS_LOG_WARN, fmt, __VA_ARGS__)
289 # define vcos_logc_info(cat,fmt,...)    _VCOS_LOG_X(cat, VCOS_LOG_INFO, fmt, __VA_ARGS__)
290 # define vcos_logc_trace(cat,fmt,...)   _VCOS_LOG_X(cat, VCOS_LOG_TRACE, fmt, __VA_ARGS__)
291 
292 # define vcos_log(fmt,...)   _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, fmt, __VA_ARGS__)
293 # define VCOS_ALERT(fmt,...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_ERROR, fmt, __VA_ARGS__)
294 # define VCOS_TRACE(fmt,...) _VCOS_LOG_X(VCOS_LOG_DFLT_CATEGORY, VCOS_LOG_INFO, fmt, __VA_ARGS__)
295 
296 # else /* _MSC_VER >= 1400 */
297 
298 /* do not define these */
299 
300 # endif /* _MSC_VER >= 1400 */
301 
302 #endif
303 
304 #if VCOS_HAVE_CMD
305 
306 #include "interface/vcos/vcos_cmd.h"
307 
308 /*
309  * These are the log sub-commands. They're exported here for user-mode apps which
310  * may want to call these, since the "log" command isn't registered for user-mode
311  * apps (vcdbg for example, has its own log command).
312  */
313 VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_assert_cmd( VCOS_CMD_PARAM_T *param );
314 VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_set_cmd( VCOS_CMD_PARAM_T *param );
315 VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_status_cmd( VCOS_CMD_PARAM_T *param );
316 VCOSPRE_ VCOS_STATUS_T VCOSPOST_ vcos_log_test_cmd( VCOS_CMD_PARAM_T *param );
317 #endif
318 
319 #ifdef __cplusplus
320 }
321 #endif
322 #endif /* VCOS_LOGGING_H */
323 
324 
325