Merge "[CA-Integration] fix for presence." into connectivity-abstraction
[platform/upstream/iotivity.git] / resource / csdk / connectivity / common / src / logger.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
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
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
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.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #include "logger.h"
22 #include "string.h"
23 #include "oic_logger.h"
24 #include "oic_console_logger.h"
25 #ifdef ARDUINO
26 #include "Arduino.h"
27 #include <avr/pgmspace.h>
28 #endif
29
30 #ifndef __TIZEN__
31 static oic_log_ctx_t *logCtx = 0;
32
33 static oic_log_level LEVEL_XTABLE[] =
34 { OIC_LOG_DEBUG, OIC_LOG_INFO, OIC_LOG_WARNING, OIC_LOG_ERROR, OIC_LOG_FATAL };
35
36 #endif
37
38 static const uint16_t LINE_BUFFER_SIZE = (16 * 2) + 16 +
39         1; // Show 16 bytes, 2 chars/byte, spaces between bytes, null termination
40
41 // Convert LogLevel to platform-specific severity level.  Store in PROGMEM on Arduino
42 #ifdef __ANDROID__
43 #ifdef ADB_SHELL
44 static const char *LEVEL[] =
45 {   "DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
46
47 #else
48 static android_LogPriority LEVEL[] =
49 {   ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
50 #endif
51 #elif defined __linux__
52 static const char *LEVEL[] __attribute__ ((unused)) =
53 {   "DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
54 #elif defined ARDUINO
55 #include <stdarg.h>
56
57 PROGMEM const char level0[] = "DEBUG";
58 PROGMEM const char level1[] = "INFO";
59 PROGMEM const char level2[] = "WARNING";
60 PROGMEM const char level3[] = "ERROR";
61 PROGMEM const char level4[] = "FATAL";
62
63 PROGMEM const char *const LEVEL[] =
64 {   level0, level1, level2, level3, level4};
65
66 static void OICLogString(LogLevel level, PROGMEM const char *tag, PROGMEM const char *logStr);
67 #ifdef ARDUINO_ARCH_AVR
68 //Mega2560 and other 8-bit AVR microcontrollers
69 #define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_word(addr));}
70 #elif defined ARDUINO_ARCH_SAM
71 //Arduino Due and other 32-bit ARM micro-controllers
72 #define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_dword(addr));}
73 #else
74 #define GET_PROGMEM_BUFFER(buffer, addr) { buffer[0] = '\0';}
75 #endif
76 #endif // __ANDROID__
77
78 #ifndef ARDUINO
79 #ifndef __TIZEN__
80 void OICLogConfig(oic_log_ctx_t *ctx)
81 {
82     logCtx = ctx;
83 }
84
85 void OICLogInit()
86 {
87
88 }
89
90 void OICLogShutdown()
91 {
92 #ifdef __linux__
93     if (logCtx && logCtx->destroy)
94     {
95         logCtx->destroy(logCtx);
96     }
97 #endif
98 }
99
100 /**
101  * Output a log string with the specified priority level.
102  * Only defined for Linux and Android
103  *
104  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
105  * @param tag    - Module name
106  * @param logStr - log string
107  */
108 void OICLog(LogLevel level, const char *tag, const char *logStr)
109 {
110     if (!logStr || !tag)
111     {
112         return;
113     }
114
115 #ifdef __ANDROID__
116
117 #ifdef ADB_SHELL
118     printf("%s: %s: %s\n", LEVEL[level], tag, logStr);
119 #else
120     __android_log_write(LEVEL[level], tag, logStr);
121 #endif
122
123 #elif defined __linux__
124     if (logCtx && logCtx->write_level)
125     {
126         logCtx->write_level(logCtx, LEVEL_XTABLE[level], logStr);
127
128     }
129     else
130     {
131         printf("%s: %s: %s\n", LEVEL[level], tag, logStr);
132     }
133 #endif
134 }
135
136 /**
137  * Output a variable argument list log string with the specified priority level.
138  * Only defined for Linux and Android
139  *
140  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
141  * @param tag    - Module name
142  * @param format - variadic log string
143  */
144 void OICLogv(LogLevel level, const char *tag, const char *format, ...)
145 {
146     if (!format || !tag)
147     {
148         return;
149     }
150     char buffer[MAX_LOG_V_BUFFER_SIZE];
151     memset(buffer, 0, sizeof buffer);
152     va_list args;
153     va_start(args, format);
154     vsnprintf(buffer, sizeof buffer - 1, format, args);
155     va_end(args);
156     OICLog(level, tag, buffer);
157 }
158
159 /**
160  * Output the contents of the specified buffer (in hex) with the specified priority level.
161  *
162  * @param level      - DEBUG, INFO, WARNING, ERROR, FATAL
163  * @param tag        - Module name
164  * @param buffer     - pointer to buffer of bytes
165  * @param bufferSize - max number of byte in buffer
166  */
167 void OICLogBuffer(LogLevel level, const char *tag, const uint8_t *buffer, uint16_t bufferSize)
168 {
169     if (!buffer || !tag || (bufferSize == 0))
170     {
171         return;
172     }
173
174     char lineBuffer[LINE_BUFFER_SIZE];
175     memset(lineBuffer, 0, sizeof lineBuffer);
176     int lineIndex = 0;
177     int i;
178     for (i = 0; i < bufferSize; i++)
179     {
180         // Format the buffer data into a line
181         snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]);
182         lineIndex++;
183         // Output 16 values per line
184         if (((i + 1) % 16) == 0)
185         {
186             OICLog(level, tag, lineBuffer);
187             memset(lineBuffer, 0, sizeof lineBuffer);
188             lineIndex = 0;
189         }
190     }
191     // Output last values in the line, if any
192     if (bufferSize % 16)
193     {
194         OICLog(level, tag, lineBuffer);
195     }
196 }
197 #endif //__TIZEN__
198 #else
199 /**
200  * Initialize the serial logger for Arduino
201  * Only defined for Arduino
202  */
203 void OICLogInit()
204 {
205     Serial.begin(115200);
206 }
207
208 /**
209  * Output a log string with the specified priority level.
210  * Only defined for Arduino.  Only uses PROGMEM strings
211  * for the tag parameter
212  *
213  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
214  * @param tag    - Module name
215  * @param logStr - log string
216  */
217 void OICLogString(LogLevel level, PROGMEM const char *tag, const char *logStr)
218 {
219     if (!logStr || !tag)
220     {
221         return;
222     }
223
224     char buffer[LINE_BUFFER_SIZE];
225
226     GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
227     Serial.print(buffer);
228
229     char c;
230     Serial.print(F(": "));
231     while ((c = pgm_read_byte(tag)))
232     {
233         Serial.write(c);
234         tag++;
235     }
236     Serial.print(F(": "));
237
238     Serial.println(logStr);
239 }
240
241 /**
242  * Output the contents of the specified buffer (in hex) with the specified priority level.
243  *
244  * @param level      - DEBUG, INFO, WARNING, ERROR, FATAL
245  * @param tag        - Module name
246  * @param buffer     - pointer to buffer of bytes
247  * @param bufferSize - max number of byte in buffer
248  */
249 void OICLogBuffer(LogLevel level, PROGMEM const char *tag, const uint8_t *buffer,
250                   uint16_t bufferSize)
251 {
252     if (!buffer || !tag || (bufferSize == 0))
253     {
254         return;
255     }
256
257     char lineBuffer[LINE_BUFFER_SIZE] =
258     {   0};
259     uint8_t lineIndex = 0;
260     for (uint8_t i = 0; i < bufferSize; i++)
261     {
262         // Format the buffer data into a line
263         snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]);
264         lineIndex++;
265         // Output 16 values per line
266         if (((i + 1) % 16) == 0)
267         {
268             OICLogString(level, tag, lineBuffer);
269             memset(lineBuffer, 0, sizeof lineBuffer);
270             lineIndex = 0;
271         }
272     }
273     // Output last values in the line, if any
274     if (bufferSize % 16)
275     {
276         OICLogString(level, tag, lineBuffer);
277     }
278 }
279
280 /**
281  * Output a log string with the specified priority level.
282  * Only defined for Arduino.  Uses PROGMEM strings
283  *
284  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
285  * @param tag    - Module name
286  * @param logStr - log string
287  */
288 void OICLog(LogLevel level, PROGMEM const char *tag, PROGMEM const char *logStr)
289 {
290     if (!logStr || !tag)
291     {
292         return;
293     }
294
295     char buffer[LINE_BUFFER_SIZE];
296
297     GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
298     Serial.print(buffer);
299
300     char c;
301     Serial.print(F(": "));
302     while ((c = pgm_read_byte(tag)))
303     {
304         Serial.write(c);
305         tag++;
306     }
307     Serial.print(F(": "));
308
309     while ((c = pgm_read_byte(logStr)))
310     {
311         Serial.write(c);
312         logStr++;
313     }
314     Serial.println();
315 }
316
317 /**
318  * Output a variable argument list log string with the specified priority level.
319  * Only defined for Arduino as depicted below.
320  *
321  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
322  * @param tag    - Module name
323  * @param format - variadic log string
324  */
325 void OICLogv(LogLevel level, PROGMEM const char *tag, const char *format, ...)
326 {
327     char buffer[LINE_BUFFER_SIZE];
328     va_list ap;
329     va_start(ap, format);
330
331     GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
332     Serial.print(buffer);
333
334     char c;
335     Serial.print(F(": "));
336
337     while ((c = pgm_read_byte(tag)))
338     {
339         Serial.write(c);
340         tag++;
341     }
342     Serial.print(F(": "));
343
344     vsnprintf(buffer, sizeof(buffer), format, ap);
345     for (char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines
346     {
347         if (*p == '\n')
348         {
349             Serial.write('\r');
350         }
351         Serial.write(*p);
352     }
353     Serial.println();
354     va_end(ap);
355 }
356 /**
357  * Output a variable argument list log string with the specified priority level.
358  * Only defined for Arduino as depicted below.
359  *
360  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
361  * @param tag    - Module name
362  * @param format - variadic log string
363  */
364 void OICLogv(LogLevel level, PROGMEM const char *tag, const __FlashStringHelper *format, ...)
365 {
366     char buffer[LINE_BUFFER_SIZE];
367     va_list ap;
368     va_start(ap, format);
369
370     GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
371     Serial.print(buffer);
372
373     char c;
374     Serial.print(F(": "));
375
376     while ((c = pgm_read_byte(tag)))
377     {
378         Serial.write(c);
379         tag++;
380     }
381     Serial.print(F(": "));
382
383 #ifdef __AVR__
384     vsnprintf_P(buffer, sizeof(buffer), (const char *)format, ap); // progmem for AVR
385 #else
386     vsnprintf(buffer, sizeof(buffer), (const char *)format, ap); // for the rest of the world
387 #endif
388     for (char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines
389     {
390         if (*p == '\n')
391         {
392             Serial.write('\r');
393         }
394         Serial.write(*p);
395     }
396     Serial.println();
397     va_end(ap);
398 }
399
400 #endif //ARDUINO