Porting TBStack Functionality to Arduino. The following changes were made
[platform/upstream/iotivity.git] / csdk / logger / src / logger.c
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Corporation 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
22 #include "logger.h"
23 #include "string.h"
24
25 static const uint16_t LINE_BUFFER_SIZE = (16 * 2) + 16 + 1;  // Show 16 bytes, 2 chars/byte, spaces between bytes, null termination
26
27 // Convert LogLevel to platform-specific severity level.  Store in PROGMEM on Arduino
28 #ifdef __ANDROID__
29     static android_LogPriority LEVEL[] = {ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
30 #elif defined __linux__
31     //static const char * LEVEL[] = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
32     static const char * LEVEL[] __attribute__ ((unused)) = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
33 #elif defined ARDUINO
34     #include <stdarg.h>
35
36     prog_char level0[] PROGMEM = "DEBUG";
37     prog_char level1[] PROGMEM = "INFO";
38     prog_char level2[] PROGMEM = "WARNING";
39     prog_char level3[] PROGMEM = "ERROR";
40     prog_char level4[] PROGMEM = "FATAL";
41
42     PROGMEM const prog_char * LEVEL[]  = {level0, level1, level2, level3, level4};
43
44     static void OCLogString(LogLevel level, const prog_char * tag, const char * logStr);
45 #endif
46
47
48 #if defined(__ANDROID__) || defined(__linux__)
49 /**
50  * Output a variable argument list log string with the specified priority level.
51  * Only defined for Linux and Android
52  *
53  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
54  * @param tag    - Module name
55  * @param format - variadic log string
56  */
57 void OCLogv(LogLevel level, const char * tag, const char * format, ...) {
58     if (!format || !tag) {
59         return;
60     }
61     char buffer[MAX_LOG_V_BUFFER_SIZE];
62     memset(buffer, 0, sizeof buffer);
63     va_list args;
64     va_start(args, format);
65     vsnprintf(buffer, sizeof buffer - 1, format, args);
66     va_end(args);
67     OCLog(level, tag, buffer);
68 }
69
70 /**
71  * Output a log string with the specified priority level.
72  * Only defined for Linux and Android
73  *
74  * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
75  * @param tag    - Module name
76  * @param logStr - log string
77  */
78 void OCLog(LogLevel level, const char * tag, const char * logStr) {
79     if (!logStr || !tag) {
80         return;
81     }
82
83     #ifdef __ANDROID__
84         __android_log_write(LEVEL[level], tag, logStr);
85     #elif defined __linux__
86         printf("%s: %s: %s\n", LEVEL[level], tag, logStr);
87     #endif
88 }
89
90 /**
91  * Output the contents of the specified buffer (in hex) with the specified priority level.
92  *
93  * @param level      - DEBUG, INFO, WARNING, ERROR, FATAL
94  * @param tag        - Module name
95  * @param buffer     - pointer to buffer of bytes
96  * @param bufferSize - max number of byte in buffer
97  */
98 void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint16_t bufferSize) {
99     if (!buffer || !tag || (bufferSize == 0)) {
100         return;
101     }
102
103     char lineBuffer[LINE_BUFFER_SIZE];
104     memset(lineBuffer, 0, sizeof lineBuffer);
105     int lineIndex = 0;
106     int i;
107     for (i = 0; i < bufferSize; i++) {
108         // Format the buffer data into a line
109         sprintf(&lineBuffer[lineIndex++ * 3], "%02X ", buffer[i]);
110         // Output 16 values per line
111         if (((i+1)%16) == 0) {
112             OCLog(level, tag, lineBuffer);
113             memset(lineBuffer, 0, sizeof lineBuffer);
114             lineIndex = 0;
115         }
116     }
117     // Output last values in the line, if any
118     if (bufferSize % 16) {
119         OCLog(level, tag, lineBuffer);
120     }
121 }
122
123 #endif
124
125
126
127 #ifdef ARDUINO
128     /**
129      * Initialize the serial logger for Arduino
130      * Only defined for Arduino
131      */
132     void OCLogInit() {
133     #ifdef TB_LOG
134         Serial.begin(115200);
135     #endif
136     }
137
138     /**
139      * Output a log string with the specified priority level.
140      * Only defined for Arduino.  Only uses PROGMEM strings
141      * for the tag parameter
142      *
143      * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
144      * @param tag    - Module name
145      * @param logStr - log string
146      */
147     void OCLogString(LogLevel level, const prog_char * tag, const char * logStr) {
148     #ifdef TB_LOG
149         if (!logStr || !tag) {
150           return;
151         }
152
153         char buffer[LINE_BUFFER_SIZE] = {0};
154         strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
155         Serial.print(buffer);
156
157         char c;
158         Serial.print(F(": "));
159         while ((c = pgm_read_byte(tag))) {
160           Serial.write(c);
161           tag++;
162         }
163         Serial.print(F(": "));
164
165         Serial.println(logStr);
166     #endif
167     }
168
169     /**
170      * Output the contents of the specified buffer (in hex) with the specified priority level.
171      *
172      * @param level      - DEBUG, INFO, WARNING, ERROR, FATAL
173      * @param tag        - Module name
174      * @param buffer     - pointer to buffer of bytes
175      * @param bufferSize - max number of byte in buffer
176      */
177     void OCLogBuffer(LogLevel level, const prog_char * tag, const uint8_t * buffer, uint16_t bufferSize) {
178     #ifdef TB_LOG
179         if (!buffer || !tag || (bufferSize == 0)) {
180             return;
181         }
182
183         char lineBuffer[LINE_BUFFER_SIZE] = {0};
184         uint8_t lineIndex = 0;
185         for (uint8_t i = 0; i < bufferSize; i++) {
186             // Format the buffer data into a line
187             sprintf(&lineBuffer[lineIndex++ * 3], "%02X ", buffer[i]);
188             // Output 16 values per line
189             if (((i+1)%16) == 0) {
190                 OCLogString(level, tag, lineBuffer);
191                 memset(lineBuffer, 0, sizeof lineBuffer);
192                 lineIndex = 0;
193             }
194         }
195         // Output last values in the line, if any
196         if (bufferSize % 16) {
197             OCLogString(level, tag, lineBuffer);
198         }
199     #endif
200     }
201
202     /**
203      * Output a log string with the specified priority level.
204      * Only defined for Arduino.  Uses PROGMEM strings
205      *
206      * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
207      * @param tag    - Module name
208      * @param logStr - log string
209      */
210     void OCLog(LogLevel level, const prog_char * tag, const prog_char * logStr) {
211     #ifdef TB_LOG
212         if (!logStr || !tag) {
213           return;
214         }
215
216         char buffer[LINE_BUFFER_SIZE] = {0};
217         strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
218         Serial.print(buffer);
219
220         char c;
221         Serial.print(F(": "));
222         while ((c = pgm_read_byte(tag))) {
223           Serial.write(c);
224           tag++;
225         }
226         Serial.print(F(": "));
227
228         while ((c = pgm_read_byte(logStr))) {
229           Serial.write(c);
230           logStr++;
231         }
232         Serial.println();
233     #endif
234     }
235
236     /**
237      * Output a variable argument list log string with the specified priority level.
238      * Only defined for Arduino as depicted below.
239      *
240      * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
241      * @param tag    - Module name
242      * @param format - variadic log string
243      */
244     void OCLogv(LogLevel level, const prog_char * tag, const char *format, ...)
245     {
246     #ifdef TB_LOG
247         char buffer[LINE_BUFFER_SIZE];
248         va_list ap;
249         va_start(ap, format);
250         strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
251         Serial.print(buffer);
252
253         char c;
254         Serial.print(F(": "));
255
256         while ((c = pgm_read_byte(tag))) {
257           Serial.write(c);
258           tag++;
259         }
260         Serial.print(F(": "));
261
262         vsnprintf(buffer, sizeof(buffer), format, ap);
263         for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines
264         {
265             if(*p == '\n')
266             {
267                 Serial.write('\r');
268             }
269             Serial.write(*p);
270         }
271         Serial.println();
272         va_end(ap);
273     #endif
274     }
275     /**
276      * Output a variable argument list log string with the specified priority level.
277      * Only defined for Arduino as depicted below.
278      *
279      * @param level  - DEBUG, INFO, WARNING, ERROR, FATAL
280      * @param tag    - Module name
281      * @param format - variadic log string
282      */
283     void OCLogv(LogLevel level, const prog_char * tag, const __FlashStringHelper *format, ...)
284     {
285     #ifdef TB_LOG
286         char buffer[LINE_BUFFER_SIZE];
287         va_list ap;
288         va_start(ap, format);
289         strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
290         Serial.print(buffer);
291
292         char c;
293         Serial.print(F(": "));
294
295         while ((c = pgm_read_byte(tag))) {
296           Serial.write(c);
297           tag++;
298         }
299         Serial.print(F(": "));
300
301         #ifdef __AVR__
302             vsnprintf_P(buffer, sizeof(buffer), (const char *)format, ap); // progmem for AVR
303         #else
304             vsnprintf(buffer, sizeof(buffer), (const char *)format, ap); // for the rest of the world
305         #endif
306         for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines
307         {
308             if(*p == '\n')
309             {
310                 Serial.write('\r');
311             }
312             Serial.write(*p);
313         }
314         Serial.println();
315         va_end(ap);
316     #endif
317     }
318
319
320 #endif
321
322