Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 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 | * |
Oana Medvesan | edfb720 | 2013-02-06 21:58:30 +0100 | [diff] [blame^] | 8 | * <!-- Copyright Trustonic 2012-2013 --> |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 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 | |
Lukas Hänel | db4b53e | 2012-10-22 13:49:41 +0200 | [diff] [blame] | 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 | */ |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 60 | |
| 61 | #define EOL "\n" |
| 62 | #define DUMMY_FUNCTION() do{}while(0) |
| 63 | |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 64 | #ifdef LOG_ANDROID |
Lukas Hänel | db4b53e | 2012-10-22 13:49:41 +0200 | [diff] [blame] | 65 | // log to adb logcat |
| 66 | #ifdef NDEBUG // no logging in debug version |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 67 | #define LOG_I(fmt, args...) DUMMY_FUNCTION() |
| 68 | #define LOG_W(fmt, args...) DUMMY_FUNCTION() |
| 69 | #else |
Lukas Hänel | db4b53e | 2012-10-22 13:49:41 +0200 | [diff] [blame] | 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__) |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 73 | #endif |
Lukas Hänel | db4b53e | 2012-10-22 13:49:41 +0200 | [diff] [blame] | 74 | // LOG_E is always defined |
| 75 | #define _LOG_E(fmt, args...) LOG_e(fmt, ## args) |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 76 | |
Lukas Hänel | db4b53e | 2012-10-22 13:49:41 +0200 | [diff] [blame] | 77 | // actually mapping to log system, adding level and tag. |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 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) |
Lukas Hänel | db4b53e | 2012-10-22 13:49:41 +0200 | [diff] [blame] | 83 | // log to std.out using printf |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 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 | |
Lukas Hänel | db4b53e | 2012-10-22 13:49:41 +0200 | [diff] [blame] | 97 | #ifdef NDEBUG // no logging in debug version |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 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 | |
Lukas Hänel | db4b53e | 2012-10-22 13:49:41 +0200 | [diff] [blame] | 108 | #if defined(LOG_VERBOSE) |
| 109 | #define LOG_V LOG_I |
| 110 | #else |
| 111 | #define LOG_V(...) DUMMY_FUNCTION() |
| 112 | #endif |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 113 | |
| 114 | /** LOG_E() needs to be more prominent: |
| 115 | * Display "*********** ERROR ***********" before actual error message. |
| 116 | */ |
| 117 | #define LOG_E(...) \ |
| 118 | do \ |
| 119 | { \ |
Lukas Hänel | db4b53e | 2012-10-22 13:49:41 +0200 | [diff] [blame] | 120 | _LOG_E(" *****************************"); \ |
| 121 | _LOG_E(" *** ERROR: "__VA_ARGS__); \ |
Oana Medvesan | edfb720 | 2013-02-06 21:58:30 +0100 | [diff] [blame^] | 122 | _LOG_E(" *** Detected in %s/%u()", __FUNCTION__, __LINE__); \ |
Lukas Hänel | db4b53e | 2012-10-22 13:49:41 +0200 | [diff] [blame] | 123 | _LOG_E(" *****************************"); \ |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 124 | } while(1!=1) |
| 125 | |
Lukas Hänel | db4b53e | 2012-10-22 13:49:41 +0200 | [diff] [blame] | 126 | #define LOG_ERRNO(MESSAGE) \ |
| 127 | LOG_E("%s failed with \"%s\"(errno %i)", MESSAGE, strerror(errno), errno); |
Lukas Hänel | f6f0f3d | 2012-05-21 11:21:57 +0200 | [diff] [blame] | 128 | |
| 129 | #define LOG_I_BUF LOG_I_Buf |
| 130 | |
| 131 | __attribute__ ((unused)) |
| 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 | /** @} */ |