• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** Log wrapper for Android.
2  * @{
3  * @file
4  *
5  * Maps LOG_*() macros to __android_log_print() if LOG_ANDROID is defined.
6  * Adds some extra info to log output like LOG_TAG, file name and line number.
7  *
8  * <!-- Copyright Giesecke & Devrient GmbH 2010 - 2011 -->
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. The name of the author may not be used to endorse or promote
19  *    products derived from this software without specific prior
20  *    written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
23  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
28  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
30  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33  */
34 #ifndef TLCWRAPPERANDROIDLOG_H_
35 #define TLCWRAPPERANDROIDLOG_H_
36 
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <android/log.h>
40 
41 /** LOG_I(fmt, args...)
42  * Informative logging, only shown in debug version
43  */
44 
45 /** LOG_W(fmt, args...)
46  * Warnings logging, only shown in debug version
47  */
48 
49 /** LOG_E(fmt, args...)
50  * Error logging, shown in debug and release version
51  */
52 
53 /** LOG_V(fmt, args...)
54  * Verbose logging, shown in debug version if the including file defines LOG_VERBOSE
55  */
56 
57 /** LOG_I_BUF(szDescriptor, blob, sizeOfBlob)
58  * Binary logging, line-wise output to LOG_I
59  */
60 
61 #define EOL "\n"
62 #define DUMMY_FUNCTION()    do{}while(0)
63 
64 #ifdef LOG_ANDROID
65 // log to adb logcat
66 #ifdef NDEBUG // no logging in debug version
67     #define LOG_I(fmt, args...) DUMMY_FUNCTION()
68     #define LOG_W(fmt, args...) DUMMY_FUNCTION()
69 #else
70     // add LINE
71     #define LOG_I(fmt, args...) LOG_i(fmt";%d", ## args, __LINE__)
72     #define LOG_W(fmt, args...) LOG_w(fmt";%d", ## args, __LINE__)
73 #endif
74     // LOG_E is always defined
75     #define _LOG_E(fmt, args...) LOG_e(fmt, ## args)
76 
77     // actually mapping to log system, adding level and tag.
78     #define LOG_i(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
79     #define LOG_w(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
80     #define LOG_e(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
81 
82 #else //!defined(LOG_ANDROID)
83 // log to std.out using printf
84 
85     // #level / #LOG_TAG ( process_id): __VA_ARGS__
86     // Example:
87     // I/McDrvBasicTest_0_1( 4075): setUp
88     #define _LOG_x(_x_,...) \
89                 do \
90                 { \
91                     printf("%s/%s(%d): ",_x_,LOG_TAG,getpid()); \
92                     printf(__VA_ARGS__); \
93                     printf(EOL); \
94                 } while(1!=1)
95 
96 
97 #ifdef NDEBUG // no logging in debug version
98     #define LOG_I(fmt, args...) DUMMY_FUNCTION()
99     #define LOG_W(fmt, args...) DUMMY_FUNCTION()
100 #else
101     #define LOG_I(...)  _LOG_x("I",__VA_ARGS__)
102     #define LOG_W(...)  _LOG_x("W",__VA_ARGS__)
103 #endif
104     #define _LOG_E(...)  _LOG_x("E",__VA_ARGS__)
105 
106 #endif //defined(LOG_ANDROID)
107 
108 #if defined(LOG_VERBOSE)
109 #define LOG_V LOG_I
110 #else
111 #define LOG_V(...) DUMMY_FUNCTION()
112 #endif
113 
114 /** LOG_E() needs to be more prominent:
115  * Display "*********** ERROR ***********" before actual error message.
116  */
117 #define LOG_E(...) \
118             do \
119             { \
120                 _LOG_E("  *****************************"); \
121                 _LOG_E("  *** ERROR: "__VA_ARGS__); \
122                 _LOG_E("  *** Detected in %s:%i/%s()", __FILE__, __LINE__, __FUNCTION__); \
123                 _LOG_E("  *****************************"); \
124             } while(1!=1)
125 
126 #define LOG_ERRNO(MESSAGE) \
127     LOG_E("%s failed with \"%s\"(errno %i)", MESSAGE, strerror(errno), errno);
128 
129 #define LOG_I_BUF   LOG_I_Buf
130 
131 __attribute__ ((unused))
LOG_I_Buf(const char * szDescriptor,const void * blob,size_t sizeOfBlob)132 static void LOG_I_Buf(
133 	const char *  szDescriptor,
134 	const void *  blob,
135 	size_t        sizeOfBlob
136 ) {
137 
138 	#define CPL         0x10  // chars per line
139 	#define OVERHEAD    20
140 
141 	char buffer[CPL * 4 + OVERHEAD];
142 
143 	uint32_t index = 0;
144 
145 	uint32_t moreThanOneLine = (sizeOfBlob > CPL);
146 	uint32_t blockLen = CPL;
147 	uint32_t addr = 0;
148 	uint32_t i = 0;
149 
150 	if (NULL != szDescriptor)
151 	{
152 		index += sprintf(&buffer[index], "%s", szDescriptor);
153 	}
154 
155 	if (moreThanOneLine)
156 	{
157 		if (NULL == szDescriptor)
158 		{
159 			index += sprintf(&buffer[index], "memory dump");
160 		}
161 		index += sprintf(&buffer[index], " (0x%08x, %d bytes)", (uint32_t)blob,sizeOfBlob);
162 		LOG_I("%s", buffer);
163 		index = 0;
164 	}
165 	else if (NULL == szDescriptor)
166 	{
167 		index += sprintf(&buffer[index], "Data at 0x%08x: ", (uint32_t)blob);
168 	}
169 
170 	if(sizeOfBlob == 0) {
171 		LOG_I("%s", buffer);
172 	}
173 	else
174 	{
175 		while (sizeOfBlob > 0)
176 		{
177 			if (sizeOfBlob < blockLen)
178 			{
179 				blockLen = sizeOfBlob;
180 			}
181 
182 			// address
183 			if (moreThanOneLine)
184 			{
185 				index += sprintf(&buffer[index], "0x%08X | ",addr);
186 				addr += CPL;
187 			}
188 			// bytes as hex
189 			for (i=0; i<blockLen; ++i)
190 			{
191 				index += sprintf(&buffer[index], "%02x ", ((const char *)blob)[i] );
192 			}
193 			// spaces if necessary
194 			if ((blockLen < CPL) && (moreThanOneLine))
195 			{
196 				// add spaces
197 				for (i=0; i<(3*(CPL-blockLen)); ++i) {
198 				index += sprintf(&buffer[index], " ");
199 				}
200 			}
201 			// bytes as ASCII
202 			index += sprintf(&buffer[index], "| ");
203 			for (i=0; i<blockLen; ++i)
204 			{
205 				char c = ((const char *)blob)[i];
206 				index += sprintf(&buffer[index], "%c",(c>32)?c:'.');
207 			}
208 
209 			blob = &(((const char *)blob)[blockLen]);
210 			sizeOfBlob -= blockLen;
211 
212 			// print line to logcat / stdout
213 			LOG_I("%s", buffer);
214 			index = 0;
215 		}
216 	}
217 }
218 
219 #endif /** TLCWRAPPERANDROIDLOG_H_ */
220 
221 /** @} */
222