From da432cdc35ddc3e2e1374f7fc46210b4a92e6f54 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 15 Dec 2019 19:13:26 +0100 Subject: libosmocore libusb integration Osmocom applications typically use libosmocore select.[ch] event loop code as their main event dispatch mechanism. When they want to deal with libusb in a non-blocking/asynchronous way, they need to integrate libusb into that select(). The new libosmousb is doing exactly that: Providing a shared utility library for Osmocom programs that wish to use libusb. This is useful for example in simtrace2 host utilitie as well as osmo-e1d. Change-Id: I656a1a38cbb5b1f3a9145d2869d3b4d0adefcae3 Closes: OS#4299 --- Makefile.am | 5 +- configure.ac | 15 +++++ contrib/jenkins_arm.sh | 1 + debian/control | 18 ++++++ debian/libosmousb0.install | 1 + include/Makefile.am | 5 ++ include/osmocom/usb/libusb.h | 6 ++ libosmousb.pc.in | 11 ++++ src/usb/Makefile.am | 21 +++++++ src/usb/osmo_libusb.c | 137 +++++++++++++++++++++++++++++++++++++++++++ 10 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 debian/libosmousb0.install create mode 100644 include/osmocom/usb/libusb.h create mode 100644 libosmousb.pc.in create mode 100644 src/usb/Makefile.am create mode 100644 src/usb/osmo_libusb.c diff --git a/Makefile.am b/Makefile.am index 7b6ba0ae..7390f982 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,11 +1,12 @@ ACLOCAL_AMFLAGS = -I m4 AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -SUBDIRS = include src src/vty src/codec src/gsm src/coding src/gb src/ctrl src/sim src/pseudotalloc utils tests +SUBDIRS = include src src/vty src/codec src/gsm src/coding src/gb src/ctrl src/sim src/pseudotalloc src/usb utils tests pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = libosmocore.pc libosmocodec.pc libosmovty.pc libosmogsm.pc \ - libosmogb.pc libosmoctrl.pc libosmocoding.pc libosmosim.pc + libosmogb.pc libosmoctrl.pc libosmocoding.pc libosmosim.pc \ + libosmousb.pc aclocaldir = $(datadir)/aclocal dist_aclocal_DATA = m4/osmo_ac_code_coverage.m4 \ diff --git a/configure.ac b/configure.ac index 060d081e..e45ec9f1 100644 --- a/configure.ac +++ b/configure.ac @@ -146,6 +146,19 @@ AS_IF([test "x$ENABLE_PCSC" = "xyes"], [ AM_CONDITIONAL(ENABLE_PCSC, test "x$ENABLE_PCSC" = "xyes") AC_SUBST(ENABLE_PCSC) +AC_ARG_ENABLE([libusb], [AS_HELP_STRING([--disable-libusb], [Build without libusb support])], + [ + ENABLE_LIBUSB=$enableval + ], + [ + ENABLE_LIBUSB="yes" + ]) +AS_IF([test "x$ENABLE_LIBUSB" = "xyes"], [ + PKG_CHECK_MODULES(LIBUSB, libusb-1.0) +]) +AM_CONDITIONAL(ENABLE_LIBUSB, test "x$ENABLE_LIBUSB" = "xyes") +AC_SUBST(ENABLE_LIBUSB) + AC_ARG_ENABLE([gnutls], [AS_HELP_STRING([--disable-gnutls], [Do not use GnuTLS fallback for missing getrandom()])], [ENABLE_GNUTLS=$enableval], [ENABLE_GNUTLS="yes"]) AM_CONDITIONAL(ENABLE_GNUTLS, test x"$ENABLE_GNUTLS" = x"yes") @@ -398,12 +411,14 @@ AC_OUTPUT( libosmogb.pc libosmoctrl.pc libosmosim.pc + libosmousb.pc include/Makefile src/Makefile src/vty/Makefile src/codec/Makefile src/coding/Makefile src/sim/Makefile + src/usb/Makefile src/gsm/Makefile src/gb/Makefile src/ctrl/Makefile diff --git a/contrib/jenkins_arm.sh b/contrib/jenkins_arm.sh index 8ee90f03..c9cd922e 100755 --- a/contrib/jenkins_arm.sh +++ b/contrib/jenkins_arm.sh @@ -19,6 +19,7 @@ build() { --disable-doxygen \ --disable-shared \ --disable-libsctp \ + --disable-libusb \ --enable-external-tests \ CFLAGS="-Os -ffunction-sections -fdata-sections -nostartfiles -nodefaultlibs $WERROR_FLAGS" diff --git a/debian/control b/debian/control index cf7a8538..d2c232fd 100644 --- a/debian/control +++ b/debian/control @@ -34,6 +34,7 @@ Depends: libosmocodec0 (= ${binary:Version}), libosmovty4 (= ${binary:Version}), libosmoctrl0 (= ${binary:Version}), libosmosim0 (= ${binary:Version}), + libosmousb0 (= ${binary:Version}), ${misc:Depends} Description: Open Source MObile COMmunications CORE library (metapackage) The libraries provided by this package contain various utility functions. @@ -293,6 +294,23 @@ Description: Osmo SIM library . The libosmosim library in particular contains routines for SIM card access. +Package: libosmousb0 +Section: libs +Architecture: any +Multi-Arch: same +Depends: ${shlibs:Depends}, + ${misc:Depends} +Pre-Depends: ${misc:Pre-Depends} +Description: Osmo USB library + This is part of the libosmocore "meta"-library. The libosmocore library + contains various utility functions that were originally developed as part of + the OpenBSC project, but which are of a more generic nature and thus useful to + (at least) other programs that are developed in the sphere of Free Software / + Open Source mobile communication. + . + The libosmosub library in particular contains routines for USB device access + via libusb-1.0, integrated into the libosmocore select event loop. + Package: libosmocore-dev Architecture: any Multi-Arch: same diff --git a/debian/libosmousb0.install b/debian/libosmousb0.install new file mode 100644 index 00000000..4031b9f4 --- /dev/null +++ b/debian/libosmousb0.install @@ -0,0 +1 @@ +usr/lib/*/libosmousb*.so.* diff --git a/include/Makefile.am b/include/Makefile.am index d76addd0..dc6eaa7f 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -164,6 +164,11 @@ nobase_include_HEADERS += \ osmocom/ctrl/control_vty.h endif +if ENABLE_LIBUSB +nobase_include_HEADERS += \ + osmocom/usb/libusb.h +endif + noinst_HEADERS = \ osmocom/gsm/kasumi.h \ osmocom/gsm/gea.h \ diff --git a/include/osmocom/usb/libusb.h b/include/osmocom/usb/libusb.h new file mode 100644 index 00000000..7f10f74c --- /dev/null +++ b/include/osmocom/usb/libusb.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +int osmo_libusb_init(libusb_context **luctx); +void osmo_libusb_exit(libusb_context *luctx); diff --git a/libosmousb.pc.in b/libosmousb.pc.in new file mode 100644 index 00000000..ce6d2715 --- /dev/null +++ b/libosmousb.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Osmocom libusb (USB) integration +Description: C Utility Library +Version: @VERSION@ +Libs: -L${libdir} @TALLOC_LIBS@ -losmousb -losmocore +Cflags: -I${includedir}/ + diff --git a/src/usb/Makefile.am b/src/usb/Makefile.am new file mode 100644 index 00000000..bca39bfe --- /dev/null +++ b/src/usb/Makefile.am @@ -0,0 +1,21 @@ +# This is _NOT_ the library release version, it's an API version. +# Please read chapter "Library interface versions" of the libtool documentation +# before making any modifications: https://www.gnu.org/software/libtool/manual/html_node/Versioning.html +LIBVERSION=0:0:0 + +AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include -I$(top_builddir)/include +AM_CFLAGS = -fPIC -Wall $(LIBUSB_CFLAGS) $(TALLOC_CFLAGS) +AM_LDFLAGS = $(COVERAGE_LDFLAGS) + +if ENABLE_LIBUSB + +lib_LTLIBRARIES = libosmousb.la + +libosmousb_la_SOURCES = osmo_libusb.c +libosmosim_la_LDFLAGS = -version-info $(LIBVERSION) +libosmosim_la_LIBADD = \ + $(top_builddir)/src/libosmocore.la \ + $(TALLOC_LIBS) \ + $(LIBUSB_LIBS) + +endif diff --git a/src/usb/osmo_libusb.c b/src/usb/osmo_libusb.c new file mode 100644 index 00000000..fda95739 --- /dev/null +++ b/src/usb/osmo_libusb.c @@ -0,0 +1,137 @@ +/* libosmocore integration with libusb-1.0 + * + * (C) 2019 by Harald Welte + * All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +/*********************************************************************** + * logging integration + ***********************************************************************/ + +#define DLUSB DLINP + +#ifdef LIBUSB_LOG_CB_CONTEXT /* introduced in 1.0.23 */ +static const int usb2logl[] = { + [LIBUSB_LOG_LEVEL_NONE] = LOGL_FATAL, + [LIBUSB_LOG_LEVEL_ERROR] = LOGL_ERROR, + [LIBUSB_LOG_LEVEL_WARNING] = LOGL_NOTICE, + [LIBUSB_LOG_LEVEL_INFO] = LOGL_INFO, + [LIBUSB_LOG_LEVEL_DEBUG] = LOGL_DEBUG, +}; + +/* called by libusb if it wants to log something */ +static void libosmo_usb_log_cb(libusb_context *luctx, enum libusb_log_level level_usb, const char *str) +{ + int level = LOGL_NOTICE; + + if (level_usb < ARRAY_SIZE(usb2logl)) + level = usb2logl[level_usb]; + + LOGP(DLUSB, level, "%s", str); +} +#endif /* LIBUSB_LOG_CB_CONTEXT */ + +/*********************************************************************** + * select loop integration + ***********************************************************************/ + +static int osmo_usb_fd_cb(struct osmo_fd *ofd, unsigned int what) +{ + libusb_context *luctx = ofd->data; + + /* we assume that we're running Linux v2.6.27 with timerfd support here + * and hence don't have to perform manual timeout handling. See + * "Notes on time-based events" at + * http://libusb.sourceforge.net/api-1.0/group__libusb__poll.html */ + struct timeval zero_tv = { 0, 0 }; + libusb_handle_events_timeout(luctx, &zero_tv); + + return 0; +} + +/* called by libusb if it wants to add a file-descriptor */ +static void osmo_usb_added_cb(int fd, short events, void *user_data) +{ + struct osmo_fd *ofd = talloc_zero(OTC_GLOBAL, struct osmo_fd); + libusb_context *luctx = user_data; + unsigned int when = 0; + + if (events & POLLIN) + when |= OSMO_FD_READ; + if (events & POLLOUT) + when |= OSMO_FD_WRITE; + + osmo_fd_setup(ofd, fd, when, osmo_usb_fd_cb, luctx, 0); + osmo_fd_register(ofd); +} + +/* called by libusb if it wants to remove a file-descriptor */ +static void osmo_usb_removed_cb(int fd, void *user_data) +{ + struct osmo_fd *ofd = osmo_fd_get_by_fd(fd); + if (!fd) + return; + osmo_fd_unregister(ofd); + talloc_free(ofd); +} + + +/*********************************************************************** + * initialization + ***********************************************************************/ + +int osmo_libusb_init(libusb_context **pluctx) +{ + libusb_context *luctx = NULL; + int rc; + + rc = libusb_init(pluctx); + if (rc != 0) + return rc; + + if (pluctx) + luctx = *pluctx; + +#ifdef LIBUSB_LOG_CB_CONTEXT /* introduced in 1.0.23 */ + libusb_set_log_cb(luctx, &libosmo_usb_log_cb, LIBUSB_LOG_CB_CONTEXT); +#endif + + libusb_set_pollfd_notifiers(luctx, osmo_usb_added_cb, osmo_usb_removed_cb, luctx); + + return 0; +} + +void osmo_libusb_exit(libusb_context *luctx) +{ + /* we just assume libusb is cleaning up all the osmo_Fd's we've allocated */ + libusb_exit(luctx); +} -- cgit v1.2.3