summaryrefslogtreecommitdiff
path: root/rbutil/jztool/src/context.c
diff options
context:
space:
mode:
Diffstat (limited to 'rbutil/jztool/src/context.c')
-rw-r--r--rbutil/jztool/src/context.c167
1 files changed, 167 insertions, 0 deletions
diff --git a/rbutil/jztool/src/context.c b/rbutil/jztool/src/context.c
new file mode 100644
index 0000000000..94b21b5196
--- /dev/null
+++ b/rbutil/jztool/src/context.c
@@ -0,0 +1,167 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2021 Aidan MacDonald
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "jztool_private.h"
23#include <string.h>
24#include <stdlib.h>
25#include <stddef.h>
26#include <stdarg.h>
27#include <stdio.h>
28#include <time.h>
29
30/** \brief Allocate a library context
31 * \returns New context or NULL if out of memory
32 */
33jz_context* jz_context_create(void)
34{
35 jz_context* jz = malloc(sizeof(struct jz_context));
36 if(!jz)
37 return NULL;
38
39 memset(jz, 0, sizeof(struct jz_context));
40 jz->log_level = JZ_LOG_ERROR;
41 return jz;
42}
43
44/** \brief Destroy the context and free its memory */
45void jz_context_destroy(jz_context* jz)
46{
47 if(jz->usb_ctx) {
48 jz_log(jz, JZ_LOG_ERROR, "BUG: USB was not cleaned up properly");
49 libusb_exit(jz->usb_ctx);
50 }
51
52 free(jz);
53}
54
55/** \brief Set a user data pointer. Useful for callbacks. */
56void jz_context_set_user_data(jz_context* jz, void* ptr)
57{
58 jz->user_data = ptr;
59}
60
61/** \brief Get the user data pointer */
62void* jz_context_get_user_data(jz_context* jz)
63{
64 return jz->user_data;
65}
66
67/** \brief Set the log message callback.
68 * \note By default, no message callback is set! No messages will be logged
69 * in this case, so ensure you set a callback if messages are desired.
70 */
71void jz_context_set_log_cb(jz_context* jz, jz_log_cb cb)
72{
73 jz->log_cb = cb;
74}
75
76/** \brief Set the log level.
77 *
78 * Messages of less importance than the set log level are not logged.
79 * The default log level is `JZ_LOG_WARNING`. The special log level
80 * `JZ_LOG_IGNORE` can be used to disable all logging temporarily.
81 *
82 * The `JZ_LOG_DEBUG` log level is extremely verbose and will log all calls,
83 * normally it's only useful for catching bugs.
84 */
85void jz_context_set_log_level(jz_context* jz, jz_log_level lev)
86{
87 jz->log_level = lev;
88}
89
90/** \brief Log an informational message.
91 * \param lev Log level for this message
92 * \param fmt `printf` style message format string
93 */
94void jz_log(jz_context* jz, jz_log_level lev, const char* fmt, ...)
95{
96 if(!jz->log_cb)
97 return;
98 if(lev == JZ_LOG_IGNORE)
99 return;
100 if(lev > jz->log_level)
101 return;
102
103 va_list ap;
104
105 va_start(ap, fmt);
106 int n = vsnprintf(NULL, 0, fmt, ap);
107 va_end(ap);
108
109 if(n < 0)
110 return;
111
112 char* buf = malloc(n + 1);
113 if(!buf)
114 return;
115
116 va_start(ap, fmt);
117 n = vsnprintf(buf, n + 1, fmt, ap);
118 va_end(ap);
119
120 if(n >= 0)
121 jz->log_cb(lev, buf);
122
123 free(buf);
124}
125
126/** \brief Log callback which writes messages to `stderr`.
127 */
128void jz_log_cb_stderr(jz_log_level lev, const char* msg)
129{
130 static const char* const tags[] =
131 {"ERROR", "WARNING", "NOTICE", "DETAIL", "DEBUG"};
132 fprintf(stderr, "[%7s] %s\n", tags[lev], msg);
133 fflush(stderr);
134}
135
136/** \brief Sleep for `ms` milliseconds.
137 */
138void jz_sleepms(int ms)
139{
140 struct timespec ts;
141 long ns = ms % 1000;
142 ts.tv_nsec = ns * 1000 * 1000;
143 ts.tv_sec = ms / 1000;
144 nanosleep(&ts, NULL);
145}
146
147int jz_context_ref_libusb(jz_context* jz)
148{
149 if(jz->usb_ctxref == 0) {
150 int rc = libusb_init(&jz->usb_ctx);
151 if(rc < 0) {
152 jz_log(jz, JZ_LOG_ERROR, "libusb_init: %s", libusb_strerror(rc));
153 return JZ_ERR_USB;
154 }
155 }
156
157 jz->usb_ctxref += 1;
158 return JZ_SUCCESS;
159}
160
161void jz_context_unref_libusb(jz_context* jz)
162{
163 if(--jz->usb_ctxref == 0) {
164 libusb_exit(jz->usb_ctx);
165 jz->usb_ctx = NULL;
166 }
167}