From b41d53792c4c4e4abd6d810b2765d865775f5104 Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Tue, 13 Apr 2021 16:58:15 +0100 Subject: jztool: New utility for installing a bootloader on FiiO M3K At present, this is just a command line tool for Linux only. Integrating this with the Rockbox utility and porting to other platforms should be straightforward; the README contains more information. Change-Id: Ie66fc837a02ab13c878925360cabc9805597548a --- rbutil/jztool/src/context.c | 167 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 rbutil/jztool/src/context.c (limited to 'rbutil/jztool/src/context.c') 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 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2021 Aidan MacDonald + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "jztool_private.h" +#include +#include +#include +#include +#include +#include + +/** \brief Allocate a library context + * \returns New context or NULL if out of memory + */ +jz_context* jz_context_create(void) +{ + jz_context* jz = malloc(sizeof(struct jz_context)); + if(!jz) + return NULL; + + memset(jz, 0, sizeof(struct jz_context)); + jz->log_level = JZ_LOG_ERROR; + return jz; +} + +/** \brief Destroy the context and free its memory */ +void jz_context_destroy(jz_context* jz) +{ + if(jz->usb_ctx) { + jz_log(jz, JZ_LOG_ERROR, "BUG: USB was not cleaned up properly"); + libusb_exit(jz->usb_ctx); + } + + free(jz); +} + +/** \brief Set a user data pointer. Useful for callbacks. */ +void jz_context_set_user_data(jz_context* jz, void* ptr) +{ + jz->user_data = ptr; +} + +/** \brief Get the user data pointer */ +void* jz_context_get_user_data(jz_context* jz) +{ + return jz->user_data; +} + +/** \brief Set the log message callback. + * \note By default, no message callback is set! No messages will be logged + * in this case, so ensure you set a callback if messages are desired. + */ +void jz_context_set_log_cb(jz_context* jz, jz_log_cb cb) +{ + jz->log_cb = cb; +} + +/** \brief Set the log level. + * + * Messages of less importance than the set log level are not logged. + * The default log level is `JZ_LOG_WARNING`. The special log level + * `JZ_LOG_IGNORE` can be used to disable all logging temporarily. + * + * The `JZ_LOG_DEBUG` log level is extremely verbose and will log all calls, + * normally it's only useful for catching bugs. + */ +void jz_context_set_log_level(jz_context* jz, jz_log_level lev) +{ + jz->log_level = lev; +} + +/** \brief Log an informational message. + * \param lev Log level for this message + * \param fmt `printf` style message format string + */ +void jz_log(jz_context* jz, jz_log_level lev, const char* fmt, ...) +{ + if(!jz->log_cb) + return; + if(lev == JZ_LOG_IGNORE) + return; + if(lev > jz->log_level) + return; + + va_list ap; + + va_start(ap, fmt); + int n = vsnprintf(NULL, 0, fmt, ap); + va_end(ap); + + if(n < 0) + return; + + char* buf = malloc(n + 1); + if(!buf) + return; + + va_start(ap, fmt); + n = vsnprintf(buf, n + 1, fmt, ap); + va_end(ap); + + if(n >= 0) + jz->log_cb(lev, buf); + + free(buf); +} + +/** \brief Log callback which writes messages to `stderr`. + */ +void jz_log_cb_stderr(jz_log_level lev, const char* msg) +{ + static const char* const tags[] = + {"ERROR", "WARNING", "NOTICE", "DETAIL", "DEBUG"}; + fprintf(stderr, "[%7s] %s\n", tags[lev], msg); + fflush(stderr); +} + +/** \brief Sleep for `ms` milliseconds. + */ +void jz_sleepms(int ms) +{ + struct timespec ts; + long ns = ms % 1000; + ts.tv_nsec = ns * 1000 * 1000; + ts.tv_sec = ms / 1000; + nanosleep(&ts, NULL); +} + +int jz_context_ref_libusb(jz_context* jz) +{ + if(jz->usb_ctxref == 0) { + int rc = libusb_init(&jz->usb_ctx); + if(rc < 0) { + jz_log(jz, JZ_LOG_ERROR, "libusb_init: %s", libusb_strerror(rc)); + return JZ_ERR_USB; + } + } + + jz->usb_ctxref += 1; + return JZ_SUCCESS; +} + +void jz_context_unref_libusb(jz_context* jz) +{ + if(--jz->usb_ctxref == 0) { + libusb_exit(jz->usb_ctx); + jz->usb_ctx = NULL; + } +} -- cgit v1.2.3