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