blob: 313dcbbd10de5efb9a1e73384cc42401cbbb1955 [file] [log] [blame]
/** Log wrapper for Android.
* @{
* @file
*
* Maps LOG_*() macros to __android_log_print() if LOG_ANDROID is defined.
* Adds some extra info to log output like LOG_TAG, file name and line number.
*
* <!-- Copyright Trustonic 2012-2013 -->
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef TLCWRAPPERANDROIDLOG_H_
#define TLCWRAPPERANDROIDLOG_H_
#include <unistd.h>
#include <stdio.h>
#include <android/log.h>
/** LOG_I(fmt, args...)
* Informative logging, only shown in debug version
*/
/** LOG_W(fmt, args...)
* Warnings logging, only shown in debug version
*/
/** LOG_E(fmt, args...)
* Error logging, shown in debug and release version
*/
/** LOG_V(fmt, args...)
* Verbose logging, shown in debug version if the including file defines LOG_VERBOSE
*/
/** LOG_I_BUF(szDescriptor, blob, sizeOfBlob)
* Binary logging, line-wise output to LOG_I
*/
#define EOL "\n"
#define DUMMY_FUNCTION() do{}while(0)
#ifdef LOG_ANDROID
// log to adb logcat
#ifdef NDEBUG // no logging in debug version
#define LOG_I(fmt, args...) DUMMY_FUNCTION()
#define LOG_W(fmt, args...) DUMMY_FUNCTION()
#else
// add LINE
#define LOG_I(fmt, args...) LOG_i(fmt";%d", ## args, __LINE__)
#define LOG_W(fmt, args...) LOG_w(fmt";%d", ## args, __LINE__)
#endif
// LOG_E is always defined
#define _LOG_E(fmt, args...) LOG_e(fmt, ## args)
// actually mapping to log system, adding level and tag.
#define LOG_i(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOG_w(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOG_e(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#else //!defined(LOG_ANDROID)
// log to std.out using printf
// #level / #LOG_TAG ( process_id): __VA_ARGS__
// Example:
// I/McDrvBasicTest_0_1( 4075): setUp
#define _LOG_x(_x_,...) \
do \
{ \
printf("%s/%s(%d): ",_x_,LOG_TAG,getpid()); \
printf(__VA_ARGS__); \
printf(EOL); \
} while(1!=1)
#ifdef NDEBUG // no logging in debug version
#define LOG_I(fmt, args...) DUMMY_FUNCTION()
#define LOG_W(fmt, args...) DUMMY_FUNCTION()
#else
#define LOG_I(...) _LOG_x("I",__VA_ARGS__)
#define LOG_W(...) _LOG_x("W",__VA_ARGS__)
#endif
#define _LOG_E(...) _LOG_x("E",__VA_ARGS__)
#endif //defined(LOG_ANDROID)
#if defined(LOG_VERBOSE)
#define LOG_V LOG_I
#else
#define LOG_V(...) DUMMY_FUNCTION()
#endif
/** LOG_E() needs to be more prominent:
* Display "*********** ERROR ***********" before actual error message.
*/
#define LOG_E(...) \
do \
{ \
_LOG_E(" *****************************"); \
_LOG_E(" *** ERROR: "__VA_ARGS__); \
_LOG_E(" *** Detected in %s/%u()", __FUNCTION__, __LINE__); \
_LOG_E(" *****************************"); \
} while(1!=1)
#define LOG_ERRNO(MESSAGE) \
LOG_E("%s failed with \"%s\"(errno %i)", MESSAGE, strerror(errno), errno);
#define LOG_I_BUF LOG_I_Buf
__attribute__ ((unused))
static void LOG_I_Buf(
const char * szDescriptor,
const void * blob,
size_t sizeOfBlob
) {
#define CPL 0x10 // chars per line
#define OVERHEAD 20
char buffer[CPL * 4 + OVERHEAD];
uint32_t index = 0;
uint32_t moreThanOneLine = (sizeOfBlob > CPL);
uint32_t blockLen = CPL;
uint32_t addr = 0;
uint32_t i = 0;
if (NULL != szDescriptor)
{
index += sprintf(&buffer[index], "%s", szDescriptor);
}
if (moreThanOneLine)
{
if (NULL == szDescriptor)
{
index += sprintf(&buffer[index], "memory dump");
}
index += sprintf(&buffer[index], " (0x%08x, %d bytes)", (uint32_t)blob,sizeOfBlob);
LOG_I("%s", buffer);
index = 0;
}
else if (NULL == szDescriptor)
{
index += sprintf(&buffer[index], "Data at 0x%08x: ", (uint32_t)blob);
}
if(sizeOfBlob == 0) {
LOG_I("%s", buffer);
}
else
{
while (sizeOfBlob > 0)
{
if (sizeOfBlob < blockLen)
{
blockLen = sizeOfBlob;
}
// address
if (moreThanOneLine)
{
index += sprintf(&buffer[index], "0x%08X | ",addr);
addr += CPL;
}
// bytes as hex
for (i=0; i<blockLen; ++i)
{
index += sprintf(&buffer[index], "%02x ", ((const char *)blob)[i] );
}
// spaces if necessary
if ((blockLen < CPL) && (moreThanOneLine))
{
// add spaces
for (i=0; i<(3*(CPL-blockLen)); ++i) {
index += sprintf(&buffer[index], " ");
}
}
// bytes as ASCII
index += sprintf(&buffer[index], "| ");
for (i=0; i<blockLen; ++i)
{
char c = ((const char *)blob)[i];
index += sprintf(&buffer[index], "%c",(c>32)?c:'.');
}
blob = &(((const char *)blob)[blockLen]);
sizeOfBlob -= blockLen;
// print line to logcat / stdout
LOG_I("%s", buffer);
index = 0;
}
}
}
#endif /** TLCWRAPPERANDROIDLOG_H_ */
/** @} */