Added connectivity files for full code review
[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 /*
215  void OCLogString(LogLevel level, PROGMEM const char * tag, const char * logStr) {
216  if (!logStr || !tag) {
217  return;
218  }
219
220  char buffer[LINE_BUFFER_SIZE] = {0};
221  strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
222  Serial.print(buffer);
223
224  char c;
225  Serial.print(F(": "));
226  while ((c = pgm_read_byte(tag))) {
227  Serial.write(c);
228  tag++;
229  }
230  Serial.print(F(": "));
231
232  Serial.println(logStr);
233  }
234  */
235 /**
236  * Output the contents of the specified buffer (in hex) with the specified priority level.
237  *
238  * @param level      - DEBUG, INFO, WARNING, ERROR, FATAL
239  * @param tag        - Module name
240  * @param buffer     - pointer to buffer of bytes
241  * @param bufferSize - max number of byte in buffer
242  */
243
244 /*
245  void OCLogBuffer(LogLevel level, PROGMEM const char * tag, const uint8_t * buffer, uint16_t bufferSize) {
246  if (!buffer || !tag || (bufferSize == 0)) {
247  return;
248  }
249
250  char lineBuffer[LINE_BUFFER_SIZE] = {0};
251  uint8_t lineIndex = 0;
252  for (uint8_t i = 0; i < bufferSize; i++) {
253  // Format the buffer data into a line
254  sprintf(&lineBuffer[lineIndex++ * 3], "%02X ", buffer[i]);
255  // Output 16 values per line
256  if (((i+1)%16) == 0) {
257  OCLogString(level, tag, lineBuffer);
258  memset(lineBuffer, 0, sizeof lineBuffer);
259  lineIndex = 0;
260  }
261  }
262  // Output last values in the line, if any
263  if (bufferSize % 16) {
264  OCLogString(level, tag, lineBuffer);
265  }
266  }
267  */
268 /**
269  * Output a log string with the specified priority level.
270  * Only defined for Arduino.  Uses PROGMEM strings
271  *
272  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
273  * @param tag    - Module name
274  * @param logStr - log string
275  */
276 void OICLog(LogLevel level, PROGMEM const char *tag, const int16_t lineNum,
277               PROGMEM const char *logStr)
278 {
279     if (!logStr || !tag)
280     {
281         return;
282     }
283     char buffer[LINE_BUFFER_SIZE] = {0};
284     strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
285     Serial.print(buffer);
286     char c;
287     Serial.print(F(": "));
288     while ((c = pgm_read_byte(tag)))
289     {
290         Serial.write(c);
291         tag++;
292     }
293     Serial.print(F(": "));
294     Serial.print(lineNum);
295     Serial.print(F(": "));
296     while ((c = pgm_read_byte(logStr)))
297     {
298         Serial.write(c);
299         logStr++;
300     }
301     Serial.println();
302 }
303
304 /**
305  * Output a variable argument list log string with the specified priority level.
306  * Only defined for Arduino as depicted below.
307  *
308  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
309  * @param tag    - Module name
310  * @param format - variadic log string
311  */
312 void OICLogv(LogLevel level, PROGMEM const char *tag, const int16_t lineNum,
313                 PROGMEM const char *format, ...)
314 {
315     char buffer[LINE_BUFFER_SIZE];
316     va_list ap;
317     va_start(ap, format);
318     strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
319     Serial.print(buffer);
320
321     char c;
322     Serial.print(F(": "));
323     while ((c = pgm_read_byte(tag))) {
324      Serial.write(c);
325      tag++;
326      }
327     Serial.print(F(": "));
328     Serial.print(lineNum);
329     Serial.print(F(": "));
330
331     vsnprintf_P(buffer, sizeof(buffer), format, ap);
332     for (char *p = &buffer[0]; *p; p++)
333     {
334         // emulate cooked mode for newlines
335         if (*p == '\n')
336         {
337             Serial.write('\r');
338         }
339         Serial.write(*p);
340     }
341     Serial.println();
342     va_end(ap);
343 }
344 /**
345  * Output a variable argument list log string with the specified priority level.
346  * Only defined for Arduino as depicted below.
347  *
348  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
349  * @param tag    - Module name
350  * @param format - variadic log string
351  */
352 void OICLogv(LogLevel level, const char *tag, const __FlashStringHelper *format, ...)
353 {
354     char buffer[LINE_BUFFER_SIZE];
355     va_list ap;
356     va_start(ap, format);
357     // strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
358     // Serial.print(buffer);
359
360     Serial.print(LEVEL[level]);
361     // char c;
362     Serial.print(F(": "));
363
364     /*while ((c = pgm_read_byte(tag))) {
365      Serial.write(c);
366      tag++;
367      }*/
368     Serial.print(tag);
369     Serial.print(F(": "));
370
371 #ifdef __AVR__
372     vsnprintf_P(buffer, sizeof(buffer), (const char *)format, ap); // progmem for AVR
373 #else
374     vsnprintf(buffer, sizeof(buffer), (const char *)format, ap); // for the rest of the world
375 #endif
376     for (char *p = &buffer[0]; *p; p++)
377     {
378         // emulate cooked mode for newlines
379         if (*p == '\n')
380         {
381             // Serial.write('\r');
382             Serial.print('\r');
383         }
384         //Serial.write(*p);
385         Serial.print(p);
386     }
387     Serial.println();
388     va_end(ap);
389 }
390
391 #endif //ARDUINO
392