diff options
author | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-15 21:04:28 +0100 |
---|---|---|
committer | Dominik Riebeling <Dominik.Riebeling@gmail.com> | 2021-12-24 18:05:53 +0100 |
commit | c876d3bbefe0dc00c27ca0c12d29da5874946962 (patch) | |
tree | 69f468a185a369b01998314bc3ecc19b70f4fcaa /utils/jztool/src/context.c | |
parent | 6c6f0757d7a902feb293be165d1490c42bc8e7ad (diff) | |
download | rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.tar.gz rockbox-c876d3bbefe0dc00c27ca0c12d29da5874946962.zip |
rbutil: Merge rbutil with utils folder.
rbutil uses several components from the utils folder, and can be
considered part of utils too. Having it in a separate folder is an
arbitrary split that doesn't help anymore these days, so merge them.
This also allows other utils to easily use libtools.make without the
need to navigate to a different folder.
Change-Id: I3fc2f4de19e3e776553efb5dea5f779dfec0dc21
Diffstat (limited to 'utils/jztool/src/context.c')
-rw-r--r-- | utils/jztool/src/context.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/utils/jztool/src/context.c b/utils/jztool/src/context.c new file mode 100644 index 0000000000..d269d1eece --- /dev/null +++ b/utils/jztool/src/context.c | |||
@@ -0,0 +1,177 @@ | |||
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 | #ifdef WIN32 | ||
31 | # include <windows.h> | ||
32 | #endif | ||
33 | |||
34 | /** \brief Allocate a library context | ||
35 | * \returns New context or NULL if out of memory | ||
36 | */ | ||
37 | jz_context* jz_context_create(void) | ||
38 | { | ||
39 | jz_context* jz = malloc(sizeof(struct jz_context)); | ||
40 | if(!jz) | ||
41 | return NULL; | ||
42 | |||
43 | memset(jz, 0, sizeof(struct jz_context)); | ||
44 | jz->log_level = JZ_LOG_ERROR; | ||
45 | return jz; | ||
46 | } | ||
47 | |||
48 | /** \brief Destroy the context and free its memory */ | ||
49 | void jz_context_destroy(jz_context* jz) | ||
50 | { | ||
51 | if(jz->usb_ctx) { | ||
52 | jz_log(jz, JZ_LOG_ERROR, "BUG: USB was not cleaned up properly"); | ||
53 | libusb_exit(jz->usb_ctx); | ||
54 | } | ||
55 | |||
56 | free(jz); | ||
57 | } | ||
58 | |||
59 | /** \brief Set a user data pointer. Useful for callbacks. */ | ||
60 | void jz_context_set_user_data(jz_context* jz, void* ptr) | ||
61 | { | ||
62 | jz->user_data = ptr; | ||
63 | } | ||
64 | |||
65 | /** \brief Get the user data pointer */ | ||
66 | void* jz_context_get_user_data(jz_context* jz) | ||
67 | { | ||
68 | return jz->user_data; | ||
69 | } | ||
70 | |||
71 | /** \brief Set the log message callback. | ||
72 | * \note By default, no message callback is set! No messages will be logged | ||
73 | * in this case, so ensure you set a callback if messages are desired. | ||
74 | */ | ||
75 | void jz_context_set_log_cb(jz_context* jz, jz_log_cb cb) | ||
76 | { | ||
77 | jz->log_cb = cb; | ||
78 | } | ||
79 | |||
80 | /** \brief Set the log level. | ||
81 | * | ||
82 | * Messages of less importance than the set log level are not logged. | ||
83 | * The default log level is `JZ_LOG_WARNING`. The special log level | ||
84 | * `JZ_LOG_IGNORE` can be used to disable all logging temporarily. | ||
85 | * | ||
86 | * The `JZ_LOG_DEBUG` log level is extremely verbose and will log all calls, | ||
87 | * normally it's only useful for catching bugs. | ||
88 | */ | ||
89 | void jz_context_set_log_level(jz_context* jz, jz_log_level lev) | ||
90 | { | ||
91 | jz->log_level = lev; | ||
92 | } | ||
93 | |||
94 | /** \brief Log an informational message. | ||
95 | * \param lev Log level for this message | ||
96 | * \param fmt `printf` style message format string | ||
97 | */ | ||
98 | void jz_log(jz_context* jz, jz_log_level lev, const char* fmt, ...) | ||
99 | { | ||
100 | if(!jz->log_cb) | ||
101 | return; | ||
102 | if(lev == JZ_LOG_IGNORE) | ||
103 | return; | ||
104 | if(lev > jz->log_level) | ||
105 | return; | ||
106 | |||
107 | va_list ap; | ||
108 | |||
109 | va_start(ap, fmt); | ||
110 | int n = vsnprintf(NULL, 0, fmt, ap); | ||
111 | va_end(ap); | ||
112 | |||
113 | if(n < 0) | ||
114 | return; | ||
115 | |||
116 | char* buf = malloc(n + 1); | ||
117 | if(!buf) | ||
118 | return; | ||
119 | |||
120 | va_start(ap, fmt); | ||
121 | n = vsnprintf(buf, n + 1, fmt, ap); | ||
122 | va_end(ap); | ||
123 | |||
124 | if(n >= 0) | ||
125 | jz->log_cb(lev, buf); | ||
126 | |||
127 | free(buf); | ||
128 | } | ||
129 | |||
130 | /** \brief Log callback which writes messages to `stderr`. | ||
131 | */ | ||
132 | void jz_log_cb_stderr(jz_log_level lev, const char* msg) | ||
133 | { | ||
134 | static const char* const tags[] = | ||
135 | {"ERROR", "WARNING", "NOTICE", "DETAIL", "DEBUG"}; | ||
136 | fprintf(stderr, "[%7s] %s\n", tags[lev], msg); | ||
137 | fflush(stderr); | ||
138 | } | ||
139 | |||
140 | /** \brief Sleep for `ms` milliseconds. | ||
141 | */ | ||
142 | void jz_sleepms(int ms) | ||
143 | { | ||
144 | #ifdef WIN32 | ||
145 | Sleep(ms); | ||
146 | #else | ||
147 | struct timespec ts; | ||
148 | long ns = ms % 1000; | ||
149 | ts.tv_nsec = ns * 1000 * 1000; | ||
150 | ts.tv_sec = ms / 1000; | ||
151 | nanosleep(&ts, NULL); | ||
152 | #endif | ||
153 | } | ||
154 | |||
155 | /** \brief Add reference to libusb context, allocating it if necessary */ | ||
156 | int jz_context_ref_libusb(jz_context* jz) | ||
157 | { | ||
158 | if(jz->usb_ctxref == 0) { | ||
159 | int rc = libusb_init(&jz->usb_ctx); | ||
160 | if(rc < 0) { | ||
161 | jz_log(jz, JZ_LOG_ERROR, "libusb_init: %s", libusb_strerror(rc)); | ||
162 | return JZ_ERR_USB; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | jz->usb_ctxref += 1; | ||
167 | return JZ_SUCCESS; | ||
168 | } | ||
169 | |||
170 | /** \brief Remove reference to libusb context, freeing if it hits zero */ | ||
171 | void jz_context_unref_libusb(jz_context* jz) | ||
172 | { | ||
173 | if(--jz->usb_ctxref == 0) { | ||
174 | libusb_exit(jz->usb_ctx); | ||
175 | jz->usb_ctx = NULL; | ||
176 | } | ||
177 | } | ||