1 /*
2 * Hamlib Interface - debug
3 * Copyright (c) 2000-2010 by Stephane Fillod
4 *
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 /**
23 * \addtogroup rig
24 * @{
25 */
26
27 /**
28 * \file debug.c
29 *
30 * \brief Control Hamlib debugging functions.
31 */
32
33 #ifdef HAVE_CONFIG_H
34 # include "config.h"
35 #endif
36
37 #include <stdlib.h>
38 #include <stdarg.h>
39 #include <stdio.h> /* Standard input/output definitions */
40 #include <string.h> /* String function definitions */
41 #include <unistd.h> /* UNIX standard function definitions */
42 #include <fcntl.h> /* File control definitions */
43 #include <errno.h> /* Error number definitions */
44 #include <sys/types.h>
45 #include <unistd.h>
46 #include <time.h>
47
48 #ifdef ANDROID
49 # include <android/log.h>
50 #endif
51
52 #include <hamlib/rig.h>
53 #include <hamlib/rig_dll.h>
54 #include "misc.h"
55
56 /*! @} */
57
58
59 /**
60 * \addtogroup rig_internal
61 * @{
62 */
63
64
65 /** \brief Sets the number of hexadecimal pairs to print per line. */
66 #define DUMP_HEX_WIDTH 16
67
68
69 static int rig_debug_level = RIG_DEBUG_TRACE;
70 static int rig_debug_time_stamp = 0;
71 static FILE *rig_debug_stream;
72 static vprintf_cb_t rig_vprintf_cb;
73 static rig_ptr_t rig_vprintf_arg;
74
75 extern HAMLIB_EXPORT(void) dump_hex(const unsigned char ptr[], size_t size);
76
77 /**
78 * \brief Do a hex dump of the unsigned char array.
79 *
80 * \param ptr Pointer to a character array.
81 * \param size Number of chars to words to dump.
82 *
83 * Prints the hex dump to `stderr` via rig_debug():
84 *
85 * ```
86 * 0000 4b 30 30 31 34 35 30 30 30 30 30 30 30 35 30 32 K001450000000502
87 * 0010 30 30 0d 0a 00..
88 * ```
89 */
dump_hex(const unsigned char ptr[],size_t size)90 void dump_hex(const unsigned char ptr[], size_t size)
91 {
92 /* example
93 * 0000 4b 30 30 31 34 35 30 30 30 30 30 30 30 35 30 32 K001450000000502
94 * 0010 30 30 0d 0a 00..
95 */
96 char line[4 + 4 + 3 * DUMP_HEX_WIDTH + 4 + DUMP_HEX_WIDTH + 1];
97 int i;
98
99 if (!rig_need_debug(RIG_DEBUG_TRACE))
100 {
101 return;
102 }
103
104 line[sizeof(line) - 1] = '\0';
105
106 for (i = 0; i < size; ++i)
107 {
108 unsigned char c;
109
110 if (i % DUMP_HEX_WIDTH == 0)
111 {
112 /* new line */
113 sprintf(line + 0, "%04x", i);
114 memset(line + 4, ' ', sizeof(line) - 4 - 1);
115 }
116
117 c = ptr[i];
118
119 /* hex print */
120 sprintf(line + 8 + 3 * (i % DUMP_HEX_WIDTH), "%02x", c);
121 line[8 + 3 * (i % DUMP_HEX_WIDTH) + 2] = ' '; /* no \0 */
122
123 /* ascii print */
124 line[8 + 3 * DUMP_HEX_WIDTH + 4 + (i % DUMP_HEX_WIDTH)] = (c >= ' '
125 && c < 0x7f) ? c : '.';
126
127 /* actually print the line */
128 if (i + 1 == size || (i && i % DUMP_HEX_WIDTH == DUMP_HEX_WIDTH - 1))
129 {
130 rig_debug(RIG_DEBUG_TRACE, "%s\n", line);
131 }
132 }
133 }
134
135 /*! @} */
136
137
138 /**
139 * \addtogroup rig
140 * @{
141 */
142
143 /**
144 * \brief Change the current debug level.
145 *
146 * \param debug_level Equivalent to the `-v` option of the utilities.
147 *
148 * Allows for dynamically changing the debugging output without reinitializing
149 * the library.
150 *
151 * Useful for programs that want to enable and disable debugging
152 * output without restarting.
153 */
rig_set_debug(enum rig_debug_level_e debug_level)154 void HAMLIB_API rig_set_debug(enum rig_debug_level_e debug_level)
155 {
156 rig_debug_level = debug_level;
157 }
158
159
160 /**
161 * \brief Test if a given debug level is active.
162 *
163 * \param debug_level The level to test.
164 *
165 * May be used to determine if an action such as opening a dialog should
166 * happen only if a desired debug level is active.
167 *
168 * Also useful for dump_hex(), etc.
169 */
rig_need_debug(enum rig_debug_level_e debug_level)170 int HAMLIB_API rig_need_debug(enum rig_debug_level_e debug_level)
171 {
172 return (debug_level <= rig_debug_level);
173 }
174
175
176 /**
177 * \brief Enable or disable the time stamp on debugging output.
178 *
179 * \param flag `TRUE` or `FALSE`.
180 *
181 * Sets or unsets the flag which controls whether debugging output includes a
182 * time stamp.
183 */
rig_set_debug_time_stamp(int flag)184 void HAMLIB_API rig_set_debug_time_stamp(int flag)
185 {
186 rig_debug_time_stamp = flag;
187 }
188
189 //! @endcond
190
191
192 /**
193 * \brief Print debugging messages through `stderr` by default.
194 *
195 * \param debug_level Debug level from none to most output.
196 * \param fmt Formatted character string to print.
197 *
198 * The formatted character string is passed to the `frprintf`(3) C library
199 * call and follows its format specification.
200 */
201 #undef rig_debug
rig_debug(enum rig_debug_level_e debug_level,const char * fmt,...)202 void HAMLIB_API rig_debug(enum rig_debug_level_e debug_level,
203 const char *fmt, ...)
204 {
205 va_list ap;
206
207 if (!rig_need_debug(debug_level))
208 {
209 return;
210 }
211
212
213 va_start(ap, fmt);
214
215 if (rig_vprintf_cb)
216 {
217 rig_vprintf_cb(debug_level, rig_vprintf_arg, fmt, ap);
218 }
219 else
220 {
221 if (!rig_debug_stream)
222 {
223 rig_debug_stream = stderr;
224 }
225
226 if (rig_debug_time_stamp)
227 {
228 char buf[256];
229 fprintf(rig_debug_stream, "%s: ", date_strget(buf, sizeof(buf)));
230 }
231
232 vfprintf(rig_debug_stream, fmt, ap);
233 fflush(rig_debug_stream);
234 }
235
236 va_end(ap);
237 #ifdef ANDROID
238 int a;
239 va_start(ap, fmt);
240
241 switch (debug_level)
242 {
243 // case RIG_DEBUG_NONE:
244 case RIG_DEBUG_BUG:
245 a = ANDROID_LOG_FATAL;
246 break;
247
248 case RIG_DEBUG_ERR:
249 a = ANDROID_LOG_ERROR;
250 break;
251
252 case RIG_DEBUG_WARN:
253 a = ANDROID_LOG_WARN;
254 break;
255
256 case RIG_DEBUG_VERBOSE:
257 a = ANDROID_LOG_VERBOSE;
258 break;
259
260 case RIG_DEBUG_TRACE:
261 a = ANDROID_LOG_VERBOSE;
262 break;
263
264 default:
265 a = ANDROID_LOG_DEBUG;
266 break;
267 }
268
269 __android_log_vprint(a, PACKAGE_NAME, fmt, ap);
270
271 va_end(ap);
272 #endif
273 }
274
275
276 /**
277 * \brief Set callback to handle debugging messages.
278 *
279 * \param cb The callback function to install.
280 * \param arg A Pointer to some private data to pass later on to the callback.
281 *
282 * Install a callback for rig_debug() messages.
283 * \code
284 * int
285 * rig_message_cb(enum rig_debug_level_e debug_level,
286 * rig_ptr_t user_data,
287 * const char *fmt,
288 * va_list ap)
289 * {
290 * char buf[1024];
291 *
292 * sprintf (buf, "Message(%s) ", (char*)user_data);
293 * syslog (LOG_USER, buf);
294 * vsprintf (buf, fmt, ap);
295 * syslog (LOG_USER, buf);
296 *
297 * return RIG_OK;
298 * }
299 *
300 * . . .
301 *
302 * char *cookie = "Foo";
303 * rig_set_debug_callback (rig_message_cb, (rig_ptr_t)cookie);
304 * \endcode
305 *
306 * \return A pointer to the previous callback that was set, if any.
307 *
308 * \sa rig_debug()
309 */
rig_set_debug_callback(vprintf_cb_t cb,rig_ptr_t arg)310 vprintf_cb_t HAMLIB_API rig_set_debug_callback(vprintf_cb_t cb, rig_ptr_t arg)
311 {
312 vprintf_cb_t prev_cb = rig_vprintf_cb;
313
314 rig_vprintf_cb = cb;
315 rig_vprintf_arg = arg;
316
317 return prev_cb;
318 }
319
320
321 /**
322 * \brief Change the output stream from `stderr` a different stream.
323 *
324 * \param stream The stream to direct debugging output.
325 *
326 * \sa `FILE`(3)
327 */
rig_set_debug_file(FILE * stream)328 FILE *HAMLIB_API rig_set_debug_file(FILE *stream)
329 {
330 FILE *prev_stream = rig_debug_stream;
331
332 rig_debug_stream = stream;
333
334 return prev_stream;
335 }
336
337 /** @} */
338