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 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
24 #include "oc_logger.h"
25 #include "oc_console_logger.h"
27 static oc_log_ctx_t *logCtx = 0;
29 static oc_log_level LEVEL_XTABLE[] = {OC_LOG_DEBUG, OC_LOG_INFO, OC_LOG_WARNING, OC_LOG_ERROR, OC_LOG_FATAL};
31 static const uint16_t LINE_BUFFER_SIZE = (16 * 2) + 16 + 1; // Show 16 bytes, 2 chars/byte, spaces between bytes, null termination
33 // Convert LogLevel to platform-specific severity level. Store in PROGMEM on Arduino
35 static android_LogPriority LEVEL[] = {ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
36 #elif defined __linux__
37 static const char * LEVEL[] __attribute__ ((unused)) = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
41 PROGMEM const char level0[] = "DEBUG";
42 PROGMEM const char level1[] = "INFO";
43 PROGMEM const char level2[] = "WARNING";
44 PROGMEM const char level3[] = "ERROR";
45 PROGMEM const char level4[] = "FATAL";
47 PROGMEM const char * const LEVEL[] = {level0, level1, level2, level3, level4};
49 static void OCLogString(LogLevel level, PROGMEM const char * tag, PROGMEM const char * logStr);
50 #ifdef ARDUINO_ARCH_AVR
51 //Mega2560 and other 8-bit AVR microcontrollers
52 #define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_word(addr));}
53 #elif defined ARDUINO_ARCH_SAM
54 //Arduino Due and other 32-bit ARM micro-controllers
55 #define GET_PROGMEM_BUFFER(buffer, addr) { strcpy_P(buffer, (char*)pgm_read_dword(addr));}
57 #define GET_PROGMEM_BUFFER(buffer, addr) { buffer[0] = '\0';}
64 void OCLogConfig(oc_log_ctx_t *ctx) {
72 void OCLogShutdown() {
74 if (logCtx && logCtx->destroy)
76 logCtx->destroy(logCtx);
82 * Output a variable argument list log string with the specified priority level.
83 * Only defined for Linux and Android
85 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
86 * @param tag - Module name
87 * @param format - variadic log string
89 void OCLogv(LogLevel level, const char * tag, const char * format, ...) {
90 if (!format || !tag) {
93 char buffer[MAX_LOG_V_BUFFER_SIZE];
94 memset(buffer, 0, sizeof buffer);
96 va_start(args, format);
97 vsnprintf(buffer, sizeof buffer - 1, format, args);
99 OCLog(level, tag, buffer);
103 * Output a log string with the specified priority level.
104 * Only defined for Linux and Android
106 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
107 * @param tag - Module name
108 * @param logStr - log string
110 void OCLog(LogLevel level, const char * tag, const char * logStr) {
111 if (!logStr || !tag) {
116 __android_log_write(LEVEL[level], tag, logStr);
117 #elif defined __linux__
118 if (logCtx && logCtx->write_level)
120 logCtx->write_level(logCtx, LEVEL_XTABLE[level], logStr);
125 printf("%s: %s: %s\n", LEVEL[level], tag, logStr);
131 * Output the contents of the specified buffer (in hex) with the specified priority level.
133 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
134 * @param tag - Module name
135 * @param buffer - pointer to buffer of bytes
136 * @param bufferSize - max number of byte in buffer
138 void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint16_t bufferSize) {
139 if (!buffer || !tag || (bufferSize == 0)) {
143 char lineBuffer[LINE_BUFFER_SIZE];
144 memset(lineBuffer, 0, sizeof lineBuffer);
147 for (i = 0; i < bufferSize; i++) {
148 // Format the buffer data into a line
149 snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]);
151 // Output 16 values per line
152 if (((i+1)%16) == 0) {
153 OCLog(level, tag, lineBuffer);
154 memset(lineBuffer, 0, sizeof lineBuffer);
158 // Output last values in the line, if any
159 if (bufferSize % 16) {
160 OCLog(level, tag, lineBuffer);
166 * Initialize the serial logger for Arduino
167 * Only defined for Arduino
170 Serial.begin(115200);
174 * Output a log string with the specified priority level.
175 * Only defined for Arduino. Only uses PROGMEM strings
176 * for the tag parameter
178 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
179 * @param tag - Module name
180 * @param logStr - log string
182 void OCLogString(LogLevel level, PROGMEM const char * tag, const char * logStr) {
183 if (!logStr || !tag) {
187 char buffer[LINE_BUFFER_SIZE];
189 GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
190 Serial.print(buffer);
193 Serial.print(F(": "));
194 while ((c = pgm_read_byte(tag))) {
198 Serial.print(F(": "));
200 Serial.println(logStr);
204 * Output the contents of the specified buffer (in hex) with the specified priority level.
206 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
207 * @param tag - Module name
208 * @param buffer - pointer to buffer of bytes
209 * @param bufferSize - max number of byte in buffer
211 void OCLogBuffer(LogLevel level, PROGMEM const char * tag, const uint8_t * buffer, uint16_t bufferSize) {
212 if (!buffer || !tag || (bufferSize == 0)) {
216 char lineBuffer[LINE_BUFFER_SIZE] = {0};
217 uint8_t lineIndex = 0;
218 for (uint8_t i = 0; i < bufferSize; i++) {
219 // Format the buffer data into a line
220 snprintf(&lineBuffer[lineIndex*3], sizeof(lineBuffer)-lineIndex*3, "%02X ", buffer[i]);
222 // Output 16 values per line
223 if (((i+1)%16) == 0) {
224 OCLogString(level, tag, lineBuffer);
225 memset(lineBuffer, 0, sizeof lineBuffer);
229 // Output last values in the line, if any
230 if (bufferSize % 16) {
231 OCLogString(level, tag, lineBuffer);
236 * Output a log string with the specified priority level.
237 * Only defined for Arduino. Uses PROGMEM strings
239 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
240 * @param tag - Module name
241 * @param logStr - log string
243 void OCLog(LogLevel level, PROGMEM const char * tag, PROGMEM const char * logStr) {
244 if (!logStr || !tag) {
248 char buffer[LINE_BUFFER_SIZE];
250 GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
251 Serial.print(buffer);
254 Serial.print(F(": "));
255 while ((c = pgm_read_byte(tag))) {
259 Serial.print(F(": "));
261 while ((c = pgm_read_byte(logStr))) {
269 * Output a variable argument list log string with the specified priority level.
270 * Only defined for Arduino as depicted below.
272 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
273 * @param tag - Module name
274 * @param format - variadic log string
276 void OCLogv(LogLevel level, PROGMEM const char * tag, const char * format, ...)
278 char buffer[LINE_BUFFER_SIZE];
280 va_start(ap, format);
282 GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
283 Serial.print(buffer);
286 Serial.print(F(": "));
288 while ((c = pgm_read_byte(tag))) {
292 Serial.print(F(": "));
294 vsnprintf(buffer, sizeof(buffer), format, ap);
295 for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines
307 * Output a variable argument list log string with the specified priority level.
308 * Only defined for Arduino as depicted below.
310 * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
311 * @param tag - Module name
312 * @param format - variadic log string
314 void OCLogv(LogLevel level, PROGMEM const char * tag, const __FlashStringHelper *format, ...)
316 char buffer[LINE_BUFFER_SIZE];
318 va_start(ap, format);
320 GET_PROGMEM_BUFFER(buffer, &(LEVEL[level]));
321 Serial.print(buffer);
324 Serial.print(F(": "));
326 while ((c = pgm_read_byte(tag))) {
330 Serial.print(F(": "));
333 vsnprintf_P(buffer, sizeof(buffer), (const char *)format, ap); // progmem for AVR
335 vsnprintf(buffer, sizeof(buffer), (const char *)format, ap); // for the rest of the world
337 for(char *p = &buffer[0]; *p; p++) // emulate cooked mode for newlines