*-solaris*)
AC_MSG_RESULT([SunOS])
backend=sunos
- threads=posix
+ platform=posix
+ ;;
+ *-cygwin*)
+ AC_MSG_RESULT([Windows (using Cygwin)])
+ backend=windows
+ platform=windows
+ EXTRA_CFLAGS="-mwin32"
+ ;;
+ *-mingw* | *msys*)
+ AC_MSG_RESULT([Windows])
+ backend=windows
+ platform=windows
+ test "x$enable_shared" = xyes && create_import_lib=yes
+ EXTRA_CFLAGS="-mwin32 -fno-omit-frame-pointer"
;;
*)
- AC_MSG_ERROR([unsupported operating system $host])
+ AC_MSG_RESULT([Null])
+ AC_MSG_WARN([The host being compiled for is not supported.])
+ AC_MSG_WARN([The library may compile but will not function in any useful manner.])
+ backend=null
+ platform=posix
+ ;;
esac
+ if test "x$platform" = xposix; then
+ AC_DEFINE([PLATFORM_POSIX], [1], [Define to 1 if compiling for a POSIX platform.])
+ AC_CHECK_TYPES([nfds_t], [], [], [[#include <poll.h>]])
+ AC_CHECK_FUNCS([pipe2])
+ dnl Some compilers do not support the '-pthread' option so check for it here
+ saved_CFLAGS="${CFLAGS}"
+ CFLAGS="-Wall -Werror -pthread"
+ AC_MSG_CHECKING([if $CC recognizes -pthread])
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
+ [AC_MSG_RESULT([yes])
+ AC_SUBST(THREAD_CFLAGS, [-pthread])],
+ [AC_MSG_RESULT([no])])
+ CFLAGS="${saved_CFLAGS}"
+ dnl Android Linux and Darwin provide pthread functions directly in libc
+ dnl glibc also provides some pthread functions directly, so search for a thread-specific function
+ AC_SEARCH_LIBS([pthread_create], [pthread],
+ [test "x$ac_cv_search_pthread_create" != "xnone required" && AC_SUBST(THREAD_LIBS, [-lpthread])],
+ [], [])
+ elif test "x$platform" = xwindows; then
+ AC_DEFINE([PLATFORM_WINDOWS], [1], [Define to 1 if compiling for a Windows platform.])
+ else
+ AC_MSG_ERROR([Unknown platform])
+ fi
+
case $backend in
+ darwin)
+ AC_CHECK_FUNCS([pthread_threadid_np])
+ LIBS="${LIBS} -lobjc -Wl,-framework,IOKit -Wl,-framework,CoreFoundation"
+ ;;
+ haiku)
+ LIBS="${LIBS} -lbe"
+ ;;
linux)
- AC_DEFINE(OS_LINUX, 1, [Linux backend])
- AC_SUBST(OS_LINUX)
-
+ AC_ARG_ENABLE([usbhost_api],
+ [AC_HELP_STRING([--enable-usbhost-api], [Request to deviced to obtain dev node fds [default=no]])],
+ [], [enable_usbhost_api="no"])
+ if test "x$enable_usbhost_api" = "xyes"; then
+ PKG_CHECK_MODULES([USBHOST_API], [dbus-1])
+ AC_DEFINE(USE_USBHOST_API, 1, [Request to deviced to obtain dev node fds])
+ fi
+
+ AC_SUBST(USE_USBHOST_API)
+
- AC_SEARCH_LIBS([clock_gettime], [rt], [], [], [-pthread])
+ AC_SEARCH_LIBS([clock_gettime], [rt], [], [], [])
+ AC_CHECK_FUNCS([pthread_setname_np])
AC_ARG_ENABLE([udev],
[AC_HELP_STRING([--enable-udev], [use udev for device enumeration and hotplug support (recommended) [default=yes]])],
- [], [enable_udev=yes])
- if test "x$enable_udev" = xyes ; then
- # system has udev. use it or fail!
- AC_CHECK_HEADERS([libudev.h], [], [AC_MSG_ERROR([udev support requested but libudev header not installed])])
- AC_CHECK_LIB([udev], [udev_new], [], [AC_MSG_ERROR([udev support requested but libudev not installed])])
- AC_DEFINE(USE_UDEV, 1, [Use udev for device enumeration/hotplug])
- else
- AC_CHECK_HEADERS([asm/types.h], [], [])
- AC_CHECK_HEADERS([sys/socket.h linux/netlink.h], [], [AC_MSG_ERROR([Linux netlink headers not found])], [
- #ifdef HAVE_ASM_TYPES_H
- #include <asm/types.h>
- #endif
- #include <sys/socket.h>
- ])
- fi
- AC_SUBST(USE_UDEV)
-
- if test "x$is_backend_android" != xyes; then
- THREAD_CFLAGS="-pthread"
- LIBS="${LIBS} -pthread"
+ [use_udev=$enableval], [use_udev=yes])
+ if test "x$use_udev" = xyes; then
+ dnl system has udev. use it or fail!
+ AC_CHECK_HEADER([libudev.h], [], [AC_MSG_ERROR([udev support requested but libudev header not installed])])
+ AC_CHECK_LIB([udev], [udev_new], [], [AC_MSG_ERROR([udev support requested but libudev not installed])])
+ else
+ AC_CHECK_HEADERS([asm/types.h])
+ AC_CHECK_HEADER([linux/netlink.h], [], [AC_MSG_ERROR([Linux netlink header not found])])
+ AC_CHECK_HEADER([sys/socket.h], [], [AC_MSG_ERROR([Linux socket header not found])])
fi
-
- AC_CHECK_HEADERS([poll.h])
- AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
- ;;
- darwin)
- AC_DEFINE(OS_DARWIN, 1, [Darwin backend])
- AC_SUBST(OS_DARWIN)
- LIBS="-lobjc -Wl,-framework,IOKit -Wl,-framework,CoreFoundation"
- LTLDFLAGS="${LTLDFLAGS} -Wl,-prebind"
- AC_CHECK_HEADERS([poll.h])
- AC_CHECK_TYPE([nfds_t],
- [AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])],
- [AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument])],
- [#include <poll.h>])
- ;;
- openbsd)
- AC_DEFINE(OS_OPENBSD, 1, [OpenBSD backend])
- AC_SUBST(OS_OPENBSD)
- THREAD_CFLAGS="-pthread"
- LIBS="-pthread"
- AC_CHECK_HEADERS([poll.h])
- AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
;;
sunos)
- AC_DEFINE(OS_SUNOS, 1, [SunOS backend])
- AC_SUBST(OS_SUNOS)
- THREAD_CFLAGS="-pthread"
- LIBS="-pthread -ldevinfo"
- AC_CHECK_HEADERS([poll.h])
- AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
- ;;
- netbsd)
- AC_DEFINE(OS_NETBSD, 1, [NetBSD backend])
- AC_SUBST(OS_NETBSD)
- THREAD_CFLAGS="-pthread"
- LIBS="-pthread"
- AC_CHECK_HEADERS([poll.h])
- AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
+ LIBS="${LIBS} -ldevinfo"
;;
windows)
- AC_DEFINE(OS_WINDOWS, 1, [Windows backend])
- AC_SUBST(OS_WINDOWS)
- LIBS=""
- LTLDFLAGS="${LTLDFLAGS} -avoid-version -Wl,--add-stdcall-alias"
- AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument])
- AC_DEFINE([WINVER], 0x0501, [Oldest Windows version supported])
- AC_DEFINE([_WIN32_WINNT], 0x0501, [Oldest Windows version supported])
+ AC_CHECK_TYPES([struct timespec], [], [], [[#include <time.h>]])
+ AC_DEFINE([_WIN32_WINNT], [_WIN32_WINNT_VISTA], [Define to the oldest supported Windows version.])
+ LT_LDFLAGS="${LT_LDFLAGS} -avoid-version -Wl,--add-stdcall-alias"
;;
- haiku)
- AC_DEFINE(OS_HAIKU, 1, [Haiku backend])
- AC_SUBST(OS_HAIKU)
- LIBS="${LIBS} -lbe"
- AC_CHECK_HEADERS([poll.h])
- AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
+ *)
+ dnl no special handling required
;;
esac
fi
fi
- # Examples build
- AC_ARG_ENABLE([examples-build], [AS_HELP_STRING([--enable-examples-build],
- [build example applications [default=no]])],
+ dnl Examples build
+ AC_ARG_ENABLE([examples-build],
+ [AS_HELP_STRING([--enable-examples-build], [build example applications [default=no]])],
[build_examples=$enableval],
[build_examples=no])
- AM_CONDITIONAL(BUILD_EXAMPLES, test "x$build_examples" != xno)
- # Tests build
- AC_ARG_ENABLE([tests-build], [AS_HELP_STRING([--enable-tests-build],
- [build test applications [default=no]])],
+ dnl Tests build
+ AC_ARG_ENABLE([tests-build],
+ [AS_HELP_STRING([--enable-tests-build], [build test applications [default=no]])],
[build_tests=$enableval],
[build_tests=no])
- AM_CONDITIONAL(BUILD_TESTS, test "x$build_tests" != xno)
- # headers not available on all platforms but required on others
- AC_CHECK_HEADERS([sys/time.h])
+ AM_CONDITIONAL([BUILD_EXAMPLES], [test "x$build_examples" != xno])
+ AM_CONDITIONAL([BUILD_TESTS], [test "x$build_tests" != xno])
+ AM_CONDITIONAL([CREATE_IMPORT_LIB], [test "x$create_import_lib" = xyes])
+ AM_CONDITIONAL([OS_DARWIN], [test "x$backend" = xdarwin])
+ AM_CONDITIONAL([OS_HAIKU], [test "x$backend" = xhaiku])
+ AM_CONDITIONAL([OS_LINUX], [test "x$backend" = xlinux])
+ AM_CONDITIONAL([OS_NETBSD], [test "x$backend" = xnetbsd])
+ AM_CONDITIONAL([OS_NULL], [test "x$backend" = xnull])
+ AM_CONDITIONAL([OS_OPENBSD], [test "x$backend" = xopenbsd])
+ AM_CONDITIONAL([OS_SUNOS], [test "x$backend" = xsunos])
+ AM_CONDITIONAL([OS_WINDOWS], [test "x$backend" = xwindows])
+ AM_CONDITIONAL([PLATFORM_POSIX], [test "x$platform" = xposix])
+ AM_CONDITIONAL([PLATFORM_WINDOWS], [test "x$platform" = xwindows])
+ AM_CONDITIONAL([USE_UDEV], [test "x$use_udev" = xyes])
++AM_CONDITIONAL([USE_USBHOST_API], [test "x$enable_usbhost_api" = "xyes"])
+
+ dnl The -Wcast-function-type warning causes a flurry of warnings when compiling
+ dnl Windows with GCC 8 or later because of dynamically loaded functions
+ if test "x$backend" = xwindows; then
+ saved_CFLAGS="${CFLAGS}"
+ CFLAGS="-Werror -Wcast-function-type"
+ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [])],
+ [EXTRA_CFLAGS="${EXTRA_CFLAGS} -Wno-cast-function-type"],
+ [])
+ CFLAGS="${saved_CFLAGS}"
+ fi
- # sigaction not available on MinGW
- AC_CHECK_FUNC([sigaction], [have_sigaction=yes], [have_sigaction=no])
- AM_CONDITIONAL(HAVE_SIGACTION, test "x$have_sigaction" = xyes)
+ SHARED_CFLAGS="-Wall -Wextra -Wshadow -Wunused -Wwrite-strings -Werror=format-security -Werror=implicit-function-declaration -Werror=implicit-int -Werror=init-self -Werror=missing-prototypes -Werror=strict-prototypes -Werror=undef -Werror=uninitialized"
- # check for -fvisibility=hidden compiler support (GCC >= 3.4)
- saved_cflags="$CFLAGS"
- # -Werror required for cygwin
- CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
- [VISIBILITY_CFLAGS="-fvisibility=hidden"
- AC_DEFINE([DEFAULT_VISIBILITY], [__attribute__((visibility("default")))], [Default visibility])],
- [VISIBILITY_CFLAGS=""
- AC_DEFINE([DEFAULT_VISIBILITY], [], [Default visibility])],
- ])
- CFLAGS="$saved_cflags"
+ AM_CPPFLAGS="${EXTRA_CPPFLAGS}"
+ AC_SUBST(AM_CPPFLAGS)
- # check for -Wno-pointer-sign compiler support (GCC >= 4)
- saved_cflags="$CFLAGS"
- CFLAGS="$CFLAGS -Wno-pointer-sign"
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
- nopointersign_cflags="-Wno-pointer-sign", nopointersign_cflags="")
- CFLAGS="$saved_cflags"
+ AM_CFLAGS="-std=${c_dialect}11 ${EXTRA_CFLAGS} ${SHARED_CFLAGS}"
+ AC_SUBST(AM_CFLAGS)
- # check for -std=gnu99 compiler support
- saved_cflags="$CFLAGS"
- CFLAGS="-std=gnu99"
- AC_MSG_CHECKING([whether CC supports -std=gnu99])
- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([])],
- [AC_MSG_RESULT([yes])]
- [AM_CFLAGS="${AM_CFLAGS} -std=gnu99"],
- [AC_MSG_RESULT([no])]
- )
- CFLAGS="$saved_cflags"
+ AM_CXXFLAGS="-std=${c_dialect}++11 ${EXTRA_CFLAGS} ${SHARED_CFLAGS} -Wmissing-declarations"
+ AC_SUBST(AM_CXXFLAGS)
- AM_CFLAGS="${AM_CFLAGS} -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow ${THREAD_CFLAGS} ${VISIBILITY_CFLAGS}"
+ AC_SUBST(LT_LDFLAGS)
- AC_SUBST(AM_CFLAGS)
- AC_SUBST(LTLDFLAGS)
+ dnl set name of html output directory for doxygen
+ AC_SUBST(DOXYGEN_HTMLDIR, [api-1.0])
AC_CONFIG_FILES([libusb-1.0.pc])
AC_CONFIG_FILES([Makefile])
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
- #include <sys/stat.h>
- #include <sys/types.h>
#include <sys/utsname.h>
- #include <time.h>
+ #include <sys/vfs.h>
+ #include <unistd.h>
- #include "libusbi.h"
- #include "linux_usbfs.h"
-
+/* Tizen specific */
+#ifdef USE_USBHOST_API
+#include <dbus/dbus.h>
+#endif
+
/* sysfs vs usbfs:
* opening a usbfs node causes the device to be resumed, so we attempt to
* avoid this during enumeration.
int iso_packet_offset;
};
- static int _open(const char *path, int flags)
- {
- #if defined(O_CLOEXEC)
- if (supports_flag_cloexec)
- return open(path, flags | O_CLOEXEC);
- else
- #endif
- return open(path, flags);
- }
-
-static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
+static int _direct_open_device(struct libusb_context *ctx, const char *path,
+ mode_t mode, int silent)
{
- struct libusb_context *ctx = DEVICE_CTX(dev);
- char path[24];
int fd;
- int delay = 10000;
- fd = _open(path, mode);
- if (usbdev_names)
- sprintf(path, USBDEV_PATH "/usbdev%u.%u",
- dev->bus_number, dev->device_address);
- else
- sprintf(path, USB_DEVTMPFS_PATH "/%03u/%03u",
- dev->bus_number, dev->device_address);
-
+ fd = open(path, mode | O_CLOEXEC);
if (fd != -1)
return fd; /* Success */
return fd; /* Success */
}
- static int _get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
+ return fd;
+}
+
+#ifdef USE_USBHOST_API
+
+#define DEVICED_BUS_NAME "org.tizen.system.deviced"
+#define DEVICED_OBJECT_PATH "/Org/Tizen/System/DeviceD"
+#define DEVICED_INTERFACE_NAME DEVICED_BUS_NAME
+#define DEVICED_PATH_USBHOST DEVICED_OBJECT_PATH"/Usbhost"
+#define DEVICED_INTERFACE_USBHOST DEVICED_INTERFACE_NAME".Usbhost"
+#define METHOD_OPEN_DEVICE "OpenDevice"
+
+DBusMessage *dbus_method_sync_with_reply(const char *dest, const char *path,
+ const char *interface, const char *method, const char *param)
+{
+ DBusConnection *conn;
+ DBusMessage *msg;
+ DBusMessageIter iter;
+ DBusMessage *reply;
+ DBusError err;
+
+ conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
+ if (!conn) {
+ usbi_err(NULL, "dbus_bus_get error");
+ return NULL;
+ }
+
+ msg = dbus_message_new_method_call(dest, path, interface, method);
+ if (!msg) {
+ usbi_err(NULL, "dbus_message_new_method_call(%s:%s-%s)",
+ path, interface, method);
+ dbus_connection_unref (conn);
+ return NULL;
+ }
+
+ dbus_message_iter_init_append(msg, &iter);
+ dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, ¶m);
+
+ dbus_error_init(&err);
+
+ reply = dbus_connection_send_with_reply_and_block(conn, msg, -1, &err);
+ if (!reply) {
+ usbi_err(NULL, "dbus_connection_send error(No reply) %s %s:%s-%s",
+ dest, path, interface, method);
+ }
+
+ if (dbus_error_is_set(&err)) {
+ usbi_err(NULL, "dbus_connection_send error(%s:%s) %s %s:%s-%s",
+ err.name, err.message, dest, path, interface, method);
+ dbus_error_free(&err);
+ reply = NULL;
+ }
+
+ dbus_message_unref(msg);
+ dbus_connection_unref (conn);
+ return reply;
+}
+
+static int open_usb_device(const char *path, int *fd)
+{
+ DBusMessage *reply;
+ DBusError err;
+ int ret, rfd;
+ dbus_bool_t result;
+
+ if (!fd || !path)
+ return -EINVAL;
+
+ dbus_error_init(&err);
+
+ reply = dbus_method_sync_with_reply(DEVICED_BUS_NAME,
+ DEVICED_PATH_USBHOST,
+ DEVICED_INTERFACE_USBHOST,
+ METHOD_OPEN_DEVICE,
+ path);
+
+ if (!reply) {
+ usbi_err(NULL, "Unable to open USB device");
+ return -1;
+ }
+
+ result = dbus_message_get_args(reply, &err,
+ DBUS_TYPE_INT32, &ret,
+ DBUS_TYPE_UNIX_FD, &rfd,
+ DBUS_TYPE_INVALID);
+ if (!result) {
+ usbi_err(NULL, "Failed to get arguments: %s", err.message);
+ return -1;
+ }
+
+ if (ret >= 0)
+ *fd = rfd;
+
+ return ret;
+}
+
+static int _ask_for_open(const char *path, mode_t mode, int silent)
+{
+ int ret;
+ int fd;
+
+ ret = open_usb_device(path, &fd);
+ if (ret < 0) {
+ /*
+ * We have an error so let's set errno correctly
+ * just like open does
+ */
+ errno= -ret;
+ ret = -1;
+ } else {
+ ret = fd;
+ }
+
+ return ret;
+}
+#endif /* USE_USBHOST_API */
+
- char path[PATH_MAX];
++static int get_usbfs_fd(struct libusb_device *dev, mode_t mode, int silent)
+{
+ struct libusb_context *ctx = DEVICE_CTX(dev);
- snprintf(path, PATH_MAX, "%s/usbdev%d.%d",
- usbfs_path, dev->bus_number, dev->device_address);
++ char path[24];
+ int fd;
+
+ if (usbdev_names)
- snprintf(path, PATH_MAX, "%s/%03d/%03d",
- usbfs_path, dev->bus_number, dev->device_address);
++ sprintf(path, USBDEV_PATH "/usbdev%u.%u",
++ dev->bus_number, dev->device_address);
+ else
++ sprintf(path, USB_DEVTMPFS_PATH "/%03u/%03u",
++ dev->bus_number, dev->device_address);
+
+ fd = _direct_open_device(ctx, path, mode, silent);
+ if (fd != -1)
+ return fd; /* Success */
+
+#ifdef USE_USBHOST_API
+ /*
+ * If we are here, we were unable to go simple
+ * path and open the device directly. In Tizen
+ * we have USB security daemon (USD) which
+ * manages access rights to USB device nodes.
+ * Now let's ask him to open this device node
+ * for us.
+ */
+
+ /*
+ * USD is applicable only for RW access.
+ */
+ if (mode & O_RDWR) {
+ if (!silent)
+ usbi_info(ctx, "No direct access to device node: %s. "
+ "Trying to use deviced", path);
+
+ fd = _ask_for_open(path, mode, silent);
+ if (fd != -1)
+ return fd;
+ }
+#endif /* USE_USBHOST_API */
+
if (!silent) {
- usbi_err(ctx, "libusb couldn't open USB device %s: %s",
- path, strerror(errno));
+ usbi_err(ctx, "libusb couldn't open USB device %s, errno=%d", path, errno);
if (errno == EACCES && mode == O_RDWR)
- usbi_err(ctx, "libusb requires write access to USB "
- "device nodes.");
+ usbi_err(ctx, "libusb requires write access to USB device nodes");
}
if (errno == EACCES)