summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pashev <pashev.igor@gmail.com>2014-12-29 14:54:15 +0000
committerIgor Pashev <pashev.igor@gmail.com>2014-12-29 14:56:35 +0000
commit6fbf635a468fb86516effb0a3015b2e4736eb850 (patch)
treea452f01f08186ec52fc3b3eb91a72e25024e09d0
parent89b5407b9aa74790a64b6f32a5b14a96242ba128 (diff)
downloadlibusb-6fbf635a468fb86516effb0a3015b2e4736eb850.tar.gz
Added Solaris backend stubsHEADmaster
-rw-r--r--configure.ac23
-rw-r--r--libusb/Makefile.am6
-rw-r--r--libusb/core.c2
-rw-r--r--libusb/io.c7
-rw-r--r--libusb/libusbi.h11
-rw-r--r--libusb/os/solaris_usb.c464
6 files changed, 503 insertions, 10 deletions
diff --git a/configure.ac b/configure.ac
index 399f397..72c03be 100644
--- a/configure.ac
+++ b/configure.ac
@@ -57,6 +57,11 @@ case $host in
esac
case $host in
+*-solaris*|*-kopensolaris*)
+ AC_MSG_RESULT([Solaris-based])
+ backend="solaris"
+ threads="posix"
+ ;;
*-linux* | *-uclinux*)
AC_MSG_RESULT([Linux])
backend="linux"
@@ -100,6 +105,17 @@ case $host in
esac
case $backend in
+solaris)
+ AC_DEFINE(OS_SOLARIS, 1, [Solaris backend])
+ AC_SUBST(OS_SOLARIS)
+ AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of the second poll() argument])
+ AC_CHECK_LIB([devinfo], [di_prop_lookup_ints], [],
+ [AC_MSG_ERROR([missing libdevinfo, which is required to get USB device properties])]
+ )
+ AC_CHECK_HEADER([libdevinfo.h], [],
+ [AC_MSG_ERROR([missing libdevinfo.h])]
+ )
+ ;;
linux)
AC_DEFINE(OS_LINUX, 1, [Linux backend])
AC_SUBST(OS_LINUX)
@@ -138,7 +154,6 @@ yes)
LIBS="${LIBS} -pthread"
esac
- AC_CHECK_HEADERS([poll.h])
AC_DEFINE([POLL_NFDS_TYPE],[nfds_t],[type of second poll() argument])
;;
darwin)
@@ -146,7 +161,6 @@ darwin)
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])],
@@ -157,7 +171,6 @@ openbsd)
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])
;;
netbsd)
@@ -165,7 +178,6 @@ netbsd)
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])
;;
windows)
@@ -180,13 +192,14 @@ 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])
;;
esac
+AC_CHECK_HEADERS([poll.h])
AC_SUBST(LIBS)
+AM_CONDITIONAL(OS_SOLARIS, test "x$backend" = xsolaris)
AM_CONDITIONAL(OS_LINUX, test "x$backend" = xlinux)
AM_CONDITIONAL(OS_DARWIN, test "x$backend" = xdarwin)
AM_CONDITIONAL(OS_OPENBSD, test "x$backend" = xopenbsd)
diff --git a/libusb/Makefile.am b/libusb/Makefile.am
index 2cd7021..1cb64b8 100644
--- a/libusb/Makefile.am
+++ b/libusb/Makefile.am
@@ -4,6 +4,7 @@ AUTOMAKE_OPTIONS = subdir-objects
lib_LTLIBRARIES = libusb-1.0.la
+SOLARIS_SRC = os/solaris_usb.c
POSIX_POLL_SRC = os/poll_posix.c
LINUX_USBFS_SRC = os/linux_usbfs.c
DARWIN_USB_SRC = os/darwin_usb.c
@@ -17,12 +18,17 @@ DIST_SUBDIRS =
EXTRA_DIST = $(LINUX_USBFS_SRC) $(DARWIN_USB_SRC) $(OPENBSD_USB_SRC) \
$(NETBSD_USB_SRC) $(WINDOWS_USB_SRC) $(WINCE_USB_SRC) \
$(POSIX_POLL_SRC) \
+ $(SOLARIS_SRC) \
os/threads_posix.c os/threads_windows.c \
os/linux_udev.c os/linux_netlink.c
dist-hook:
-cp -r os/haiku $(distdir)/os/haiku
+if OS_SOLARIS
+OS_SRC = $(SOLARIS_SRC) $(POSIX_POLL_SRC)
+endif
+
if OS_LINUX
if USE_UDEV
diff --git a/libusb/core.c b/libusb/core.c
index 9894209..330a95f 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -46,6 +46,8 @@
#if defined(OS_LINUX)
const struct usbi_os_backend * const usbi_backend = &linux_usbfs_backend;
+#elif defined(OS_SOLARIS)
+const struct usbi_os_backend * const usbi_backend = &solaris_backend;
#elif defined(OS_DARWIN)
const struct usbi_os_backend * const usbi_backend = &darwin_backend;
#elif defined(OS_OPENBSD)
diff --git a/libusb/io.c b/libusb/io.c
index a5fda69..1520fb7 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -40,6 +40,13 @@
#include "libusbi.h"
#include "hotplug.h"
+#if !defined(TIMESPEC_TO_TIMEVAL)
+#define TIMESPEC_TO_TIMEVAL(tv, ts) { \
+ (tv)->tv_sec = (long)(ts)->tv_sec; \
+ (tv)->tv_usec = (long)(ts)->tv_nsec / 1000; \
+}
+#endif
+
/**
* \page io Synchronous and asynchronous device I/O
*
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
index 2d2f71a..1eee278 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -479,11 +479,11 @@ int usbi_signal_event(struct libusb_context *ctx);
int usbi_clear_event(struct libusb_context *ctx);
/* Internal abstraction for poll (needs struct usbi_transfer on Windows) */
-#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_HAIKU)
-#include <unistd.h>
-#include "os/poll_posix.h"
-#elif defined(OS_WINDOWS) || defined(OS_WINCE)
-#include "os/poll_windows.h"
+#if defined(OS_WINDOWS)
+# include <os/poll_windows.h>
+#else
+# include <unistd.h>
+# include <os/poll_posix.h>
#endif
#if (defined(OS_WINDOWS) || defined(OS_WINCE)) && !defined(__GNUC__)
@@ -1047,6 +1047,7 @@ struct usbi_os_backend {
extern const struct usbi_os_backend * const usbi_backend;
extern const struct usbi_os_backend linux_usbfs_backend;
+extern const struct usbi_os_backend solaris_backend;
extern const struct usbi_os_backend darwin_backend;
extern const struct usbi_os_backend openbsd_backend;
extern const struct usbi_os_backend netbsd_backend;
diff --git a/libusb/os/solaris_usb.c b/libusb/os/solaris_usb.c
new file mode 100644
index 0000000..5360452
--- /dev/null
+++ b/libusb/os/solaris_usb.c
@@ -0,0 +1,464 @@
+/*
+ * Copyright (c) 2013 Igor Pashev <pashev.igor@gmail.com> (http://osdyson.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <dirent.h>
+#include <errno.h>
+#include <regex.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <libdevinfo.h>
+
+#include "libusb.h"
+#include "libusbi.h"
+
+static const char dev_usb[] = "/dev/usb";
+static const char devices[] = "/devices";
+static const size_t devices_len = sizeof (devices) - 1;
+
+
+/*
+ * Backend functions
+ */
+static int solaris_get_device_list (struct libusb_context *,
+ struct discovered_devs **);
+static int solaris_open (struct libusb_device_handle *);
+static void solaris_close (struct libusb_device_handle *);
+
+static int solaris_get_device_descriptor (struct libusb_device *,
+ unsigned char *, int *);
+static int solaris_get_active_config_descriptor (struct libusb_device *,
+ unsigned char *, size_t,
+ int *);
+static int solaris_get_config_descriptor (struct libusb_device *, uint8_t,
+ unsigned char *, size_t, int *);
+
+static int solaris_get_configuration (struct libusb_device_handle *, int *);
+static int solaris_set_configuration (struct libusb_device_handle *, int);
+
+static int solaris_claim_interface (struct libusb_device_handle *, int);
+static int solaris_release_interface (struct libusb_device_handle *, int);
+
+static int solaris_set_interface_altsetting (struct libusb_device_handle *,
+ int, int);
+static int solaris_clear_halt (struct libusb_device_handle *, unsigned char);
+static int solaris_reset_device (struct libusb_device_handle *);
+static void solaris_destroy_device (struct libusb_device *);
+
+static int solaris_submit_transfer (struct usbi_transfer *);
+static int solaris_cancel_transfer (struct usbi_transfer *);
+static void solaris_clear_transfer_priv (struct usbi_transfer *);
+static int solaris_handle_events (struct libusb_context *ctx, struct pollfd *,
+ nfds_t, int);
+static int solaris_clock_gettime (int, struct timespec *);
+
+
+const struct usbi_os_backend solaris_backend = {
+ .name = "Synchronous Solaris backend",
+ .init = NULL,
+ .exit = NULL,
+ .get_device_list = solaris_get_device_list,
+ .open = solaris_open,
+ .close = solaris_close,
+
+ .get_device_descriptor = solaris_get_device_descriptor,
+ .get_active_config_descriptor = solaris_get_active_config_descriptor,
+ .get_config_descriptor = solaris_get_config_descriptor,
+
+ .get_configuration = solaris_get_configuration,
+ .set_configuration = solaris_set_configuration,
+
+ .claim_interface = solaris_claim_interface,
+ .release_interface = solaris_release_interface,
+
+ .set_interface_altsetting = solaris_set_interface_altsetting,
+ .clear_halt = solaris_clear_halt,
+ .reset_device = solaris_reset_device,
+
+ .kernel_driver_active = NULL,
+ .detach_kernel_driver = NULL,
+ .attach_kernel_driver = NULL,
+
+ .destroy_device = solaris_destroy_device,
+
+ .submit_transfer = solaris_submit_transfer,
+ .cancel_transfer = solaris_cancel_transfer,
+ .clear_transfer_priv = solaris_clear_transfer_priv,
+
+ .handle_events = solaris_handle_events,
+
+ .clock_gettime = solaris_clock_gettime,
+
+ .device_priv_size = 0,
+ .device_handle_priv_size = 0,
+ .transfer_priv_size = 0,
+ .add_iso_packet_size = 0,
+};
+
+
+static int
+di_prop_get_int (di_node_t dn, const char *propname, int *out)
+{
+ int retval;
+ int *intp;
+
+ usbi_dbg ("looking for \"%s\" property", propname);
+
+ retval = di_prop_lookup_ints (DDI_DEV_T_ANY, dn, propname, &intp);
+ if (1 == retval)
+ {
+ if (NULL != out)
+ *out = *intp;
+ usbi_dbg ("found %s = %d", propname, *intp);
+ }
+ else if (0 == retval)
+ usbi_dbg ("property \"%s\" is empty", propname);
+ else if (retval < 0)
+ usbi_dbg ("failed to get property \"%s\": %s", propname,
+ strerror (errno));
+ else
+ usbi_dbg ("got %d values of \"%s\"", retval, propname);
+
+ return retval;
+}
+
+static void
+solaris_add_device (struct libusb_context *ctx,
+ struct discovered_devs **discdevs,
+ const char *device_node_path)
+{
+ int busnum = 0;
+ int devaddr = 0;
+ int numconf = 1;
+ unsigned long session_id;
+ enum libusb_speed speed;
+
+ usbi_info (ctx, "device node \"%s\"", device_node_path);
+
+ di_node_t devnode = di_init (device_node_path, DINFOPROP);
+ if (DI_NODE_NIL == devnode)
+ {
+ usbi_err (ctx, "di_init() failed: %s, skipping", strerror (errno));
+ return;
+ }
+
+ /* From now work with libdevinfo */
+
+ if (1 != di_prop_get_int (devnode, "assigned-address", &busnum))
+ goto cleanup;
+
+ if (1 != di_prop_get_int (devnode, "usb-num-configs", &numconf))
+ goto cleanup;
+
+ /* XXX: Super speed is not supported. */
+ /* XXX: if no *-speed property exists, it is full-speed device. */
+ if (0 <= di_prop_get_int (devnode, "low-speed", NULL))
+ speed = LIBUSB_SPEED_LOW;
+ else if (0 <= di_prop_get_int (devnode, "full-speed", NULL))
+ speed = LIBUSB_SPEED_FULL;
+ else if (0 <= di_prop_get_int (devnode, "high-speed", NULL))
+ speed = LIBUSB_SPEED_HIGH;
+ else if (0 <= di_prop_get_int (devnode, "super-speed", NULL))
+ speed = LIBUSB_SPEED_SUPER;
+ else
+ speed = LIBUSB_SPEED_FULL;
+
+
+ /* get device address - a number after @ in device_node_path:
+ * in "pci@0,0/pci106b,3f@6/device@2" device address is 2
+ */
+ char *at = strrchr (device_node_path, '@');
+ if (NULL == at)
+ { /* can't happen! */
+ usbi_err (ctx,
+ "failed to parse device node to device address, skipping");
+ goto cleanup;
+ }
+ at++;
+ devaddr = atoi (at);
+
+ session_id = busnum << 8 | devaddr;
+ usbi_dbg ("busnum %d devaddr %d session_id %u", busnum, devaddr,
+ session_id);
+
+cleanup:
+ di_fini (devnode);
+ return;
+}
+
+
+int
+solaris_get_device_list (struct libusb_context *ctx,
+ struct discovered_devs **discdevs)
+{
+ char vidpid_path[sizeof ("/dev/usb/vvvv.pppp")];
+ char devstat_path[sizeof ("/dev/usb/vvvv.pppp/iiii/devstat")]; /* 9999 instances should be enough. */
+
+ /* for realpath(): */
+ char
+ device_path[sizeof
+ ("/devices/pci@NNNN,MMMM/pciXXXX,YYYY@IIII/device@IIII:AAAA.BBBB.devstat")];
+
+ regex_t regex;
+ int retval;
+ char *device_node_path;
+
+ if (0 != regcomp (&regex, "[0-9a-f]+\\.[0-9a-f]+", REG_EXTENDED))
+ {
+ usbi_err (ctx, "regcomp() failed");
+ return (LIBUSB_ERROR_NO_MEM);
+ }
+
+ /* open /dev/usb for browsing. */
+ DIR *dev_usb_dir = opendir (dev_usb);
+ if (NULL == dev_usb_dir)
+ {
+ usbi_err (ctx, "opendir(\"%s\") failed: %s", dev_usb, strerror (errno));
+ regfree (&regex);
+ return (LIBUSB_ERROR_ACCESS);
+ }
+
+ struct dirent *vidpid;
+ usbi_dbg ("start browsing %s", dev_usb);
+ while ((vidpid = readdir (dev_usb_dir)) != NULL)
+ {
+ if (0 != regexec (&regex, vidpid->d_name, 0, NULL, 0))
+ {
+ if ('.' != vidpid->d_name[0])
+ usbi_dbg ("skipping %s", vidpid->d_name);
+ continue;
+ }
+
+ usbi_dbg ("found %s", vidpid->d_name);
+
+ retval =
+ snprintf (vidpid_path, sizeof (vidpid_path), "%s/%s", dev_usb,
+ vidpid->d_name);
+ if (retval >= sizeof (vidpid_path))
+ {
+ usbi_err (ctx, "vidpid_path: snprintf() failed, skipping");
+ continue;
+ }
+
+ /* open /dev/usb/<VID>.<PID> for browsing. */
+ DIR *vidpid_dir = opendir (vidpid_path);
+ if (NULL == vidpid_dir)
+ {
+ usbi_err (ctx, "opendir(\"%s\") failed: %s, skipping", vidpid_path,
+ strerror (errno));
+ continue;
+ }
+
+ struct dirent *inst;
+ usbi_dbg ("start browsing %s", vidpid_path);
+ while ((inst = readdir (vidpid_dir)) != NULL)
+ {
+ if ('.' == inst->d_name[0])
+ continue;
+
+ usbi_dbg ("found instance %s", inst->d_name);
+
+ usbi_info (ctx, "found ugen device %s/%s", vidpid_path,
+ inst->d_name);
+
+ /* We need *any* file in the instance subdir
+ * only to get the real device path under /devices.
+ * E. g. given /dev/usb/a12.1/0/devstat -> /devices/pci@0,0/pci106b,3f@6/device@2:a12.1.devstat
+ * we should get /devices/pci@0,0/pci106b,3f@6/device@2
+ * devstat always exists, so use it.
+ */
+ retval =
+ snprintf (devstat_path, sizeof (devstat_path), "%s/%s/devstat",
+ vidpid_path, inst->d_name);
+ if (retval >= sizeof (devstat_path))
+ {
+ usbi_err (ctx, "devstat_path: snprintf() failed, skipping");
+ continue;
+ }
+
+ device_node_path = realpath (devstat_path, device_path);
+ if (NULL == device_node_path)
+ {
+ usbi_err (ctx, "realpath() for \"%s\" failed: %s", devstat_path,
+ strerror (errno));
+ continue;
+ }
+
+ usbi_dbg ("device path \"%s\"", device_path);
+
+ /* is real path under /devices directory? */
+ if (strncmp (device_path, devices, devices_len) != 0)
+ {
+ /* No */
+ usbi_warn (ctx, "\"%s\" is not under /devices, skipping",
+ device_path);
+ continue;
+ }
+
+ /* for di_init() we need to:
+ *
+ * a) strip /devices from the beginning of device_path
+ * b) strip everything after the colon in device_path
+ *
+ * E. g. /devices/pci@0,0/pci106b,3f@6/device@2:a12.1.devstat
+ * should become /pci@0,0/pci106b,3f@6/device@2
+ */
+
+ /* a) */
+ device_node_path += devices_len;
+
+ /* b) */
+ char *colon = strrchr (device_node_path, ':');
+ if (colon)
+ *colon = '\0';
+ else
+ usbi_warn (ctx, "no colon in device node path");
+
+ solaris_add_device (ctx, discdevs, device_node_path);
+ }
+ usbi_dbg ("stop browsing %s", vidpid_path);
+ }
+ usbi_dbg ("stop browsing %s", dev_usb);
+
+ (void) closedir (dev_usb_dir);
+
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_open (struct libusb_device_handle *handle)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+void
+solaris_close (struct libusb_device_handle *handle)
+{
+}
+
+int
+solaris_get_device_descriptor (struct libusb_device *dev, unsigned char *buf,
+ int *host_endian)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_get_active_config_descriptor (struct libusb_device *dev,
+ unsigned char *buf, size_t len,
+ int *host_endian)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_get_config_descriptor (struct libusb_device *dev, uint8_t idx,
+ unsigned char *buf, size_t len,
+ int *host_endian)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_get_configuration (struct libusb_device_handle *handle, int *config)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_set_configuration (struct libusb_device_handle *handle, int config)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_claim_interface (struct libusb_device_handle *handle, int iface)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_release_interface (struct libusb_device_handle *handle, int iface)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_set_interface_altsetting (struct libusb_device_handle *handle,
+ int iface, int altsetting)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_clear_halt (struct libusb_device_handle *handle,
+ unsigned char endpoint)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_reset_device (struct libusb_device_handle *handle)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+void
+solaris_destroy_device (struct libusb_device *dev)
+{
+}
+
+int
+solaris_submit_transfer (struct usbi_transfer *itransfer)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_cancel_transfer (struct usbi_transfer *itransfer)
+{
+ usbi_dbg ("");
+
+ return (LIBUSB_ERROR_NOT_SUPPORTED);
+}
+
+void
+solaris_clear_transfer_priv (struct usbi_transfer *itransfer)
+{
+}
+
+int
+solaris_handle_events (struct libusb_context *ctx, struct pollfd *fds,
+ nfds_t nfds, int num_ready)
+{
+ return (LIBUSB_ERROR_NO_DEVICE);
+}
+
+int
+solaris_clock_gettime (int clkid, struct timespec *tp)
+{
+ usbi_dbg ("clock %d", clkid);
+
+ if (clkid == USBI_CLOCK_REALTIME)
+ return clock_gettime (CLOCK_REALTIME, tp);
+
+ if (clkid == USBI_CLOCK_MONOTONIC)
+ return clock_gettime (CLOCK_MONOTONIC, tp);
+
+ return (LIBUSB_ERROR_INVALID_PARAM);
+}