1 //******************************************************************
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 // Defining _POSIX_C_SOURCE macro with 199309L (or greater) as value
22 // causes header files to expose definitions
23 // corresponding to the POSIX.1b, Real-time extensions
24 // (IEEE Std 1003.1b-1993) specification
26 // For this specific file, see use of clock_gettime,
27 // Refer to http://pubs.opengroup.org/stage7tc1/functions/clock_gettime.html
28 // and to http://man7.org/linux/man-pages/man2/clock_gettime.2.html
29 #ifndef _POSIX_C_SOURCE
30 #define _POSIX_C_SOURCE 200809L
33 // Platform check can be extended to check and/or define more, or could be
34 // moved into a config.h
35 #if !defined(__ARDUINO__) && !defined(ARDUINO)
36 #define HAVE_UNISTD_H 1
39 // Pull in _POSIX_TIMERS feature test macro to check for
40 // clock_gettime() support.
44 // if we have unistd.h, we're a Unix system
51 #include "oc_logger.h"
52 #include "oc_console_logger.h"
55 static oc_log_ctx_t *logCtx = 0;
57 static oc_log_level LEVEL_XTABLE[] = {OC_LOG_DEBUG, OC_LOG_INFO, OC_LOG_WARNING, OC_LOG_ERROR, OC_LOG_FATAL};
60 static const uint16_t LINE_BUFFER_SIZE = (16 * 2) + 16 + 1; // Show 16 bytes, 2 chars/byte, spaces between bytes, null termination
62 // Convert LogLevel to platform-specific severity level. Store in PROGMEM on Arduino
64 static android_LogPriority LEVEL[] = {ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
65 #elif defined(__linux__) || defined(__APPLE__)
66 static const char * LEVEL[] __attribute__ ((unused)) = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
70 PROGMEM const char level0[] = "DEBUG";
71 PROGMEM const char level1[] = "INFO";
72 PROGMEM const char level2[] = "WARNING";
73 PROGMEM const char level3[] = "ERROR";
74 PROGMEM const char level4[] = "FATAL";
76 PROGMEM const char * const LEVEL[] = {level0, level1, level2, level3, level4};
78 static void OCLogString(LogLevel level, PROGMEM const char * tag, PROGMEM const char * logStr);
79 #ifdef ARDUINO_ARCH_AVR
80 //Mega2560 and other 8-bit AVR microcontrollers
81 #define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_word(addr));}
82 #elif defined ARDUINO_ARCH_SAM
83 //Arduino Due and other 32-bit ARM micro-controllers
84 #define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_dword(addr));}
86 #define GET_PROGMEM_BUFFER(buffer, addr) { buffer[0] = '\0';}
94 int OCGetTizenLogLevel(LogLevel level)
108 * Temp fix to resolve DLOG_FATAL runtime crash in tizen binary.
109 * TODO: Revert back to DLOG_FATAL once logging issue is fixed in
118 void OCLogConfig(oc_log_ctx_t *ctx) {
126 void OCLogShutdown() {
127 #if defined(__linux__) || defined(__APPLE__)
128 if (logCtx && logCtx->destroy)
130 logCtx->destroy(logCtx);
136 * Output a variable argument list log string with the specified priority level.
137 * Only defined for Linux and Android
139 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
140 * @param tag - Module name
141 * @param format - variadic log string
143 void OCLogv(LogLevel level, const char * tag, const char * format, ...) {
144 if (!format || !tag) {
147 char buffer[MAX_LOG_V_BUFFER_SIZE] = {};
149 va_start(args, format);
150 vsnprintf(buffer, sizeof buffer - 1, format, args);
152 OCLog(level, tag, buffer);
155 static void osalGetTime(int *min,int *sec, int *ms)
157 if (min && sec && ms)
159 #if defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0
160 struct timespec when = {0};
161 clockid_t clk = CLOCK_REALTIME;
162 #ifdef CLOCK_REALTIME_COARSE
163 clk = CLOCK_REALTIME_COARSE;
165 if (!clock_gettime(clk, &when))
167 *min = (when.tv_sec / 60) % 60;
168 *sec = when.tv_sec % 60;
169 *ms = when.tv_nsec / 1000000;
173 if (!gettimeofday(&now, NULL))
175 *min = (now.tv_sec / 60) % 60;
176 *sec = now.tv_sec % 60;
177 *ms = now.tv_usec * 1000;
184 * Output a log string with the specified priority level.
185 * Only defined for Linux and Android
187 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
188 * @param tag - Module name
189 * @param logStr - log string
191 void OCLog(LogLevel level, const char * tag, const char * logStr) {
192 if (!logStr || !tag) {
197 __android_log_write(LEVEL[level], tag, logStr);
198 #elif defined(__linux__) || defined(__APPLE__)
199 if (logCtx && logCtx->write_level)
201 logCtx->write_level(logCtx, LEVEL_XTABLE[level], logStr);
209 osalGetTime(&min,&sec,&ms);
211 printf("%02d:%02d.%03d %s: %s: %s\n", min, sec, ms, LEVEL[level], tag, logStr);
217 * Output the contents of the specified buffer (in hex) with the specified priority level.
219 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
220 * @param tag - Module name
221 * @param buffer - pointer to buffer of bytes
222 * @param bufferSize - max number of byte in buffer
224 void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint16_t bufferSize) {
225 if (!buffer || !tag || (bufferSize == 0)) {
229 // No idea why the static initialization won't work here, it seems the compiler is convinced
230 // that this is a variable-sized object.
231 char lineBuffer[LINE_BUFFER_SIZE];
232 memset(lineBuffer, 0, sizeof lineBuffer);
235 for (i = 0; i < bufferSize; i++) {
236 // Format the buffer data into a line
237 snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]);
239 // Output 16 values per line
240 if (((i+1)%16) == 0) {
241 OCLog(level, tag, lineBuffer);
242 memset(lineBuffer, 0, sizeof lineBuffer);
246 // Output last values in the line, if any
247 if (bufferSize % 16) {
248 OCLog(level, tag, lineBuffer);
254 * Initialize the serial logger for Arduino
255 * Only defined for Arduino
258 Serial.begin(115200);
262 * Output a log string with the specified priority level.
263 * Only defined for Arduino. Only uses PROGMEM strings
264 * for the tag parameter
266 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
267 * @param tag - Module name
268 * @param logStr - log string
270 void OCLogString(LogLevel level, PROGMEM const char * tag, const char * logStr) {
271 if (!logStr || !tag) {
275 char buffer[LINE_BUFFER_SIZE];
277 GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
278 Serial.print(buffer);
281 Serial.print(F(": "));
282 while ((c = pgm_read_byte(tag))) {
286 Serial.print(F(": "));
288 Serial.println(logStr);
292 * Output the contents of the specified buffer (in hex) with the specified priority level.
294 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
295 * @param tag - Module name
296 * @param buffer - pointer to buffer of bytes
297 * @param bufferSize - max number of byte in buffer
299 void OCLogBuffer(LogLevel level, PROGMEM const char * tag, const uint8_t * buffer, uint16_t bufferSize) {
300 if (!buffer || !tag || (bufferSize == 0)) {
304 char lineBuffer[LINE_BUFFER_SIZE] = {0};
305 uint8_t lineIndex = 0;
306 for (uint8_t i = 0; i < bufferSize; i++) {
307 // Format the buffer data into a line
308 snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]);
310 // Output 16 values per line
311 if (((i+1)%16) == 0) {
312 OCLogString(level, tag, lineBuffer);
313 memset(lineBuffer, 0, sizeof lineBuffer);
317 // Output last values in the line, if any
318 if (bufferSize % 16) {
319 OCLogString(level, tag, lineBuffer);
324 * Output a log string with the specified priority level.
325 * Only defined for Arduino. Uses PROGMEM strings
327 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
328 * @param tag - Module name
329 * @param logStr - log string
331 void OCLog(LogLevel level, PROGMEM const char * tag, PROGMEM const char * logStr) {
332 if (!logStr || !tag) {
336 char buffer[LINE_BUFFER_SIZE];
338 GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
339 Serial.print(buffer);
342 Serial.print(F(": "));
343 while ((c = pgm_read_byte(tag))) {
347 Serial.print(F(": "));
349 while ((c = pgm_read_byte(logStr))) {
357 * Output a variable argument list log string with the specified priority level.
358 * Only defined for Arduino as depicted below.
360 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
361 * @param tag - Module name
362 * @param format - variadic log string
364 void OCLogv(LogLevel level, PROGMEM const char * tag, PROGMEM const char * format, ...)
366 char buffer[LINE_BUFFER_SIZE];
368 va_start(ap, format);
370 GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
371 Serial.print(buffer);
374 Serial.print(F(": "));
376 while ((c = pgm_read_byte(tag))) {
380 Serial.print(F(": "));
383 vsnprintf_P(buffer, sizeof(buffer), format, ap);
385 vsnprintf(buffer, sizeof(buffer), format, ap);
387 for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines