From: Akshay Jaggi Date: Wed, 24 Sep 2014 21:46:17 +0000 (+0100) Subject: haiku: Add Haiku support X-Git-Tag: upstream/1.0.21~236 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dc97425bb415422423b8876af0e34111e566d56d;p=platform%2Fupstream%2Flibusb.git haiku: Add Haiku support --- diff --git a/bootstrap.sh b/bootstrap.sh index 8b2b2c0..506440b 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -12,6 +12,14 @@ else exit 1 fi +# run autotools on haiku package +cd libusb/os/haiku || exit 1 +$LIBTOOLIZE --copy --force || exit 1 +aclocal || exit 1 +autoconf || exit 1 +automake -a -c || exit 1 +cd ../../.. + $LIBTOOLIZE --copy --force || exit 1 aclocal || exit 1 autoheader || exit 1 diff --git a/configure.ac b/configure.ac index b662c0d..399f397 100644 --- a/configure.ac +++ b/configure.ac @@ -89,6 +89,12 @@ case $host in backend="windows" threads="posix" ;; +*-haiku*) + AC_MSG_RESULT([Haiku]) + AC_CONFIG_SUBDIRS([libusb/os/haiku]) + backend="haiku" + threads="posix" + ;; *) AC_MSG_ERROR([unsupported operating system]) esac @@ -170,6 +176,13 @@ windows) AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument]) AC_DEFINE([WINVER], 0x0501, [Oldest Windows version supported]) ;; +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_SUBST(LIBS) @@ -179,6 +192,7 @@ AM_CONDITIONAL(OS_DARWIN, test "x$backend" = xdarwin) AM_CONDITIONAL(OS_OPENBSD, test "x$backend" = xopenbsd) AM_CONDITIONAL(OS_NETBSD, test "x$backend" = xnetbsd) AM_CONDITIONAL(OS_WINDOWS, test "x$backend" = xwindows) +AM_CONDITIONAL(OS_HAIKU, test "x$backend" = xhaiku) AM_CONDITIONAL(THREADS_POSIX, test "x$threads" = xposix) AM_CONDITIONAL(CREATE_IMPORT_LIB, test "x$create_import_lib" = "xyes") AM_CONDITIONAL(USE_UDEV, test "x$enable_udev" = xyes) @@ -289,7 +303,18 @@ AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_FUNCS(gettimeofday) AC_CHECK_HEADERS([signal.h]) -AM_CFLAGS="${AM_CFLAGS} -std=gnu99 -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow ${THREAD_CFLAGS} ${VISIBILITY_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_CFLAGS="${AM_CFLAGS} -Wall -Wundef -Wunused -Wstrict-prototypes -Werror-implicit-function-declaration $nopointersign_cflags -Wshadow ${THREAD_CFLAGS} ${VISIBILITY_CFLAGS}" AC_SUBST(AM_CFLAGS) AC_SUBST(LTLDFLAGS) diff --git a/libusb/Makefile.am b/libusb/Makefile.am index 80e3705..b3c2f05 100644 --- a/libusb/Makefile.am +++ b/libusb/Makefile.am @@ -12,6 +12,9 @@ NETBSD_USB_SRC = os/netbsd_usb.c WINDOWS_USB_SRC = os/poll_windows.c os/windows_usb.c libusb-1.0.rc libusb-1.0.def WINCE_USB_SRC = os/wince_usb.c os/wince_usb.h +dist_data_DATA = os/haiku +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) \ @@ -43,6 +46,11 @@ if OS_NETBSD OS_SRC = $(NETBSD_USB_SRC) $(POSIX_POLL_SRC) endif +if OS_HAIKU +OS_SRC = $(POSIX_POLL_SRC) +SUBDIRS = os/haiku +endif + if OS_WINDOWS OS_SRC = $(WINDOWS_USB_SRC) @@ -71,5 +79,9 @@ libusb_1_0_la_SOURCES = libusbi.h core.c descriptor.c io.c strerror.c sync.c \ hotplug.h hotplug.c $(THREADS_SRC) $(OS_SRC) \ os/poll_posix.h os/poll_windows.h +if OS_HAIKU +libusb_1_0_la_LIBADD = os/haiku/libhaikuusb.la +endif + hdrdir = $(includedir)/libusb-1.0 hdr_HEADERS = libusb.h diff --git a/libusb/core.c b/libusb/core.c index 4561740..c24ab77 100644 --- a/libusb/core.c +++ b/libusb/core.c @@ -56,6 +56,8 @@ const struct usbi_os_backend * const usbi_backend = &netbsd_backend; const struct usbi_os_backend * const usbi_backend = &windows_backend; #elif defined(OS_WINCE) const struct usbi_os_backend * const usbi_backend = &wince_backend; +#elif defined(OS_HAIKU) +const struct usbi_os_backend * const usbi_backend = &haiku_usb_raw_backend; #else #error "Unsupported OS" #endif diff --git a/libusb/libusb.h b/libusb/libusb.h index a19ab34..79b255f 100644 --- a/libusb/libusb.h +++ b/libusb/libusb.h @@ -54,7 +54,7 @@ typedef unsigned __int32 uint32_t; #include #endif -#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) +#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__) #include #endif diff --git a/libusb/libusbi.h b/libusb/libusbi.h index 8d1fb9d..98cc4eb 100644 --- a/libusb/libusbi.h +++ b/libusb/libusbi.h @@ -48,6 +48,10 @@ */ #define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY +#ifdef __cplusplus +extern "C" { +#endif + #define DEVICE_DESC_LENGTH 18 #define USB_MAXENDPOINTS 32 @@ -145,8 +149,12 @@ static inline void *usbi_reallocf(void *ptr, size_t size) const typeof( ((type *)0)->member ) *mptr = (ptr); \ (type *)( (char *)mptr - offsetof(type,member) );}) +#ifndef MIN #define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif +#ifndef MAX #define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif #define TIMESPEC_IS_SET(ts) ((ts)->tv_sec != 0 || (ts)->tv_nsec != 0) @@ -454,7 +462,7 @@ void usbi_connect_device (struct libusb_device *dev); void usbi_disconnect_device (struct libusb_device *dev); /* Internal abstraction for poll (needs struct usbi_transfer on Windows) */ -#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) +#if defined(OS_LINUX) || defined(OS_DARWIN) || defined(OS_OPENBSD) || defined(OS_NETBSD) || defined(OS_HAIKU) #include #include "os/poll_posix.h" #elif defined(OS_WINDOWS) || defined(OS_WINCE) @@ -1027,8 +1035,13 @@ extern const struct usbi_os_backend openbsd_backend; extern const struct usbi_os_backend netbsd_backend; extern const struct usbi_os_backend windows_backend; extern const struct usbi_os_backend wince_backend; +extern const struct usbi_os_backend haiku_usb_raw_backend; extern struct list_head active_contexts_list; extern usbi_mutex_static_t active_contexts_lock; +#ifdef __cplusplus +} +#endif + #endif diff --git a/libusb/os/haiku/Makefile.am b/libusb/os/haiku/Makefile.am new file mode 100644 index 0000000..3ab0a09 --- /dev/null +++ b/libusb/os/haiku/Makefile.am @@ -0,0 +1,5 @@ +ACLOCAL_AMFLAGS = -I m4 +AUTOMAKE_OPTIONS = subdir-objects +noinst_LTLIBRARIES = libhaikuusb.la +libhaikuusb_la_CPPFLAGS = $(AM_CPPFLAGS) -I../.. -I../../.. +libhaikuusb_la_SOURCES = haiku_usb_raw.cpp haiku_usb_backend.cpp haiku_pollfs.cpp diff --git a/libusb/os/haiku/configure.ac b/libusb/os/haiku/configure.ac new file mode 100644 index 0000000..ae95179 --- /dev/null +++ b/libusb/os/haiku/configure.ac @@ -0,0 +1,8 @@ +AC_INIT([haikuusb], [1.0]) +AM_INIT_AUTOMAKE([no-define foreign]) +AM_MAINTAINER_MODE +AC_CONFIG_MACRO_DIR([m4]) +LT_INIT +AC_PROG_CXX +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/libusb/os/haiku/haiku_pollfs.cpp b/libusb/os/haiku/haiku_pollfs.cpp new file mode 100644 index 0000000..6781de4 --- /dev/null +++ b/libusb/os/haiku/haiku_pollfs.cpp @@ -0,0 +1,378 @@ +/* + * Copyright 2007-2008, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Lotz + */ + +#include "haiku_usb.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class WatchedEntry { +public: + WatchedEntry(BMessenger*, entry_ref*); + ~WatchedEntry(); + bool EntryCreated(entry_ref* ref); + bool EntryRemoved(ino_t node); + bool InitCheck(); + +private: + BMessenger* fMessenger; + node_ref fNode; + bool fIsDirectory; + USBDevice* fDevice; + WatchedEntry* fEntries; + WatchedEntry* fLink; + bool fInitCheck; +}; + + +class RosterLooper : public BLooper { +public: + RosterLooper(USBRoster*); + void Stop(); + virtual void MessageReceived(BMessage*); + bool InitCheck(); + +private: + USBRoster* fRoster; + WatchedEntry* fRoot; + BMessenger* fMessenger; + bool fInitCheck; +}; + + +WatchedEntry::WatchedEntry(BMessenger* messenger, entry_ref* ref) + : fMessenger(messenger), + fIsDirectory(false), + fDevice(NULL), + fEntries(NULL), + fLink(NULL), + fInitCheck(false) +{ + BEntry entry(ref); + entry.GetNodeRef(&fNode); + + BDirectory directory; + if (entry.IsDirectory() && directory.SetTo(ref) >= B_OK) { + + fIsDirectory = true; + + while (directory.GetNextEntry(&entry) >= B_OK) { + if (entry.GetRef(ref) < B_OK) + continue; + + WatchedEntry* child = new(std::nothrow) WatchedEntry(fMessenger, ref); + if (child == NULL) + continue; + if (child->InitCheck() == false) + { + delete child; + continue; + } + + + child->fLink = fEntries; + fEntries = child; + } + + watch_node(&fNode, B_WATCH_DIRECTORY, *fMessenger); + + } else { + if (strncmp(ref->name, "raw", 3) == 0) + return; + + BPath path, parent_path; + entry.GetPath(&path); + fDevice = new(std::nothrow) USBDevice(path.Path()); + if (fDevice != NULL && fDevice->InitCheck() == true) { + // Add this new device to each active context's device list + struct libusb_context *ctx; + unsigned long session_id = (unsigned long)&fDevice; + + usbi_mutex_lock(&active_contexts_lock); + list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { + + struct libusb_device* dev = usbi_get_device_by_session_id(ctx, session_id); + if (dev) { + usbi_dbg("using previously allocated device with location %lu", session_id); + libusb_unref_device(dev); + continue; + } + usbi_dbg("allocating new device with location %lu" ,session_id); + dev = usbi_alloc_device(ctx, session_id); + if (!dev) { + usbi_dbg("device allocation failed"); + continue; + } + *((USBDevice**)dev->os_priv) = fDevice; + + // Calculate pseudo-device-address + int addr,tmp; + if (strcmp(path.Leaf(), "hub") == 0) + { + tmp=100; //Random Number + } + else + { + sscanf(path.Leaf(), "%d", &tmp); + } + addr = tmp + 1; + path.GetParent(&parent_path); + while(strcmp(parent_path.Leaf(),"usb") != 0) + { + sscanf(parent_path.Leaf(), "%d", &tmp); + addr += tmp + 1; + parent_path.GetParent(&parent_path); + } + sscanf(path.Path(), "/dev/bus/usb/%d", &dev->bus_number); + (dev->device_address) = addr - (dev->bus_number + 1); + + if(usbi_sanitize_device(dev) < 0) + { + usbi_dbg("device sanitization failed"); + libusb_unref_device(dev); + continue; + } + usbi_connect_device(dev); + } + usbi_mutex_unlock(&active_contexts_lock); + } else if (fDevice) { + delete fDevice; + fDevice = NULL; + return; + } + } + fInitCheck = true; +} + + +WatchedEntry::~WatchedEntry() +{ + if (fIsDirectory) { + watch_node(&fNode, B_STOP_WATCHING, *fMessenger); + + WatchedEntry* child = fEntries; + while (child) { + WatchedEntry *next = child->fLink; + delete child; + child = next; + } + } + + if (fDevice) { + // Remove this device from each active context's device list + struct libusb_context *ctx; + struct libusb_device *dev; + unsigned long session_id = (unsigned long)&fDevice; + + usbi_mutex_lock(&active_contexts_lock); + list_for_each_entry(ctx, &active_contexts_list, list, struct libusb_context) { + dev = usbi_get_device_by_session_id (ctx, session_id); + if (dev != NULL) { + usbi_disconnect_device (dev); + libusb_unref_device(dev); + } else { + usbi_dbg("device with location %lu not found", session_id); + } + } + usbi_mutex_static_unlock(&active_contexts_lock); + delete fDevice; + } +} + + +bool +WatchedEntry::EntryCreated(entry_ref *ref) +{ + if (!fIsDirectory) + return false; + + if (ref->directory != fNode.node) { + WatchedEntry* child = fEntries; + while (child) { + if (child->EntryCreated(ref)) + return true; + child = child->fLink; + } + return false; + } + + WatchedEntry* child = new(std::nothrow) WatchedEntry(fMessenger, ref); + if (child == NULL) + return false; + child->fLink = fEntries; + fEntries = child; + return true; +} + + +bool +WatchedEntry::EntryRemoved(ino_t node) +{ + if (!fIsDirectory) + return false; + + WatchedEntry* child = fEntries; + WatchedEntry* lastChild = NULL; + while (child) { + if (child->fNode.node == node) { + if (lastChild) + lastChild->fLink = child->fLink; + else + fEntries = child->fLink; + delete child; + return true; + } + + if (child->EntryRemoved(node)) + return true; + + lastChild = child; + child = child->fLink; + } + return false; +} + + +bool +WatchedEntry::InitCheck() +{ + return fInitCheck; +} + + +RosterLooper::RosterLooper(USBRoster* roster) + : BLooper("LibusbRoster Looper"), + fRoster(roster), + fRoot(NULL), + fMessenger(NULL), + fInitCheck(false) +{ + BEntry entry("/dev/bus/usb"); + if (!entry.Exists()) { + usbi_err(NULL,"usb_raw not published"); + return; + } + + Run(); + fMessenger = new(std::nothrow) BMessenger(this); + if (fMessenger == NULL) + { + usbi_err(NULL,"error creating BMessenger object"); + return; + } + + if(Lock()) { + entry_ref ref; + entry.GetRef(&ref); + fRoot = new(std::nothrow) WatchedEntry(fMessenger, &ref); + Unlock(); + if (fRoot == NULL) + { + return; + } + if (fRoot->InitCheck() == false) + { + delete fRoot; + return; + } + } + fInitCheck = true; +} + + +void +RosterLooper::Stop() +{ + Lock(); + delete fRoot; + delete fMessenger; + Quit(); +} + + +void +RosterLooper::MessageReceived(BMessage *message) +{ + int32 opcode; + if (message->FindInt32("opcode", &opcode) < B_OK) + return; + + switch (opcode) { + case B_ENTRY_CREATED: { + dev_t device; + ino_t directory; + const char* name; + if (message->FindInt32("device", &device) < B_OK + || message->FindInt64("directory", &directory) < B_OK + || message->FindString("name", &name) < B_OK) + break; + + entry_ref ref(device, directory, name); + fRoot->EntryCreated(&ref); + break; + } + case B_ENTRY_REMOVED: { + ino_t node; + if (message->FindInt64("node", &node) < B_OK) + break; + fRoot->EntryRemoved(node); + break; + } + } +} + + +bool +RosterLooper::InitCheck() +{ + return fInitCheck; +} + + +USBRoster::USBRoster() + : fLooper(NULL) +{ +} + + +USBRoster::~USBRoster() +{ + Stop(); +} + + +int +USBRoster::Start() +{ + if(fLooper) + return LIBUSB_SUCCESS; + + fLooper = new(std::nothrow) RosterLooper(this); + if (fLooper == NULL || ((RosterLooper*)fLooper)->InitCheck() == false) + return LIBUSB_ERROR_OTHER; + return LIBUSB_SUCCESS; +} + + +void +USBRoster::Stop() +{ + if(!fLooper) + return; + + ((RosterLooper *)fLooper)->Stop(); + fLooper = NULL; +} + + diff --git a/libusb/os/haiku/haiku_usb.h b/libusb/os/haiku/haiku_usb.h new file mode 100644 index 0000000..0188191 --- /dev/null +++ b/libusb/os/haiku/haiku_usb.h @@ -0,0 +1,114 @@ +/* + * Haiku Backend for libusb + * Copyright © 2014 Akshay Jaggi + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include +#include +#include +#include "libusbi.h" +#include "haiku_usb_raw.h" + +using namespace std; + +class USBDevice; +class USBDeviceHandle; +class USBTransfer; + +class USBDevice { +public: + USBDevice(const char *); + virtual ~USBDevice(); + const char* Location() const; + uint8 CountConfigurations() const; + const usb_device_descriptor* Descriptor() const; + const usb_configuration_descriptor* ConfigurationDescriptor(uint32) const; + const usb_configuration_descriptor* ActiveConfiguration() const; + uint8 EndpointToIndex(uint8) const; + uint8 EndpointToInterface(uint8) const; + int ClaimInterface(int); + int ReleaseInterface(int); + int CheckInterfacesFree(int); + int SetActiveConfiguration(int); + int ActiveConfigurationIndex() const; + bool InitCheck(); +private: + int Initialise(); + unsigned int fClaimedInterfaces; // Max Interfaces can be 32. Using a bitmask + usb_device_descriptor fDeviceDescriptor; + unsigned char** fConfigurationDescriptors; + int fActiveConfiguration; + char* fPath; + map fConfigToIndex; + map* fEndpointToIndex; + map* fEndpointToInterface; + bool fInitCheck; +}; + +class USBDeviceHandle { +public: + USBDeviceHandle(USBDevice* dev); + virtual ~USBDeviceHandle(); + int EventPipe(int) const; + int ClaimInterface(int); + int ReleaseInterface(int); + int SetConfiguration(int); + int SetAltSetting(int,int); + status_t SubmitTransfer(struct usbi_transfer*); + status_t CancelTransfer(USBTransfer*); + bool InitCheck(); +private: + int fRawFD; + static status_t TransfersThread(void *); + void TransfersWorker(); + USBDevice* fUSBDevice; + unsigned int fClaimedInterfaces; + int fEventPipes[2]; + BList fTransfers; + BLocker fTransfersLock; + sem_id fTransfersSem; + thread_id fTransfersThread; + bool fInitCheck; +}; + +class USBTransfer { +public: + USBTransfer(struct usbi_transfer*,USBDevice*); + virtual ~USBTransfer(); + void Do(int); + struct usbi_transfer* UsbiTransfer(); + void SetCancelled(); + bool IsCancelled(); +private: + struct usbi_transfer* fUsbiTransfer; + struct libusb_transfer* fLibusbTransfer; + USBDevice* fUSBDevice; + BLocker fStatusLock; + bool fCancelled; +}; + +class USBRoster { +public: + USBRoster(); + virtual ~USBRoster(); + int Start(); + void Stop(); +private: + void* fLooper; +}; diff --git a/libusb/os/haiku/haiku_usb_backend.cpp b/libusb/os/haiku/haiku_usb_backend.cpp new file mode 100644 index 0000000..471bda9 --- /dev/null +++ b/libusb/os/haiku/haiku_usb_backend.cpp @@ -0,0 +1,562 @@ +/* + * Haiku Backend for libusb + * Copyright © 2014 Akshay Jaggi + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include + +#include "haiku_usb.h" + +int _errno_to_libusb(int status) +{ + return status; +} + +USBTransfer::USBTransfer(struct usbi_transfer* itransfer, USBDevice* device) +{ + fUsbiTransfer=itransfer; + fLibusbTransfer=USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + fUSBDevice=device; + fCancelled=false; +} + +USBTransfer::~USBTransfer() +{ +} + +struct usbi_transfer* +USBTransfer::UsbiTransfer() +{ + return fUsbiTransfer; +} + +void +USBTransfer::SetCancelled() +{ + fCancelled=true; +} + +bool +USBTransfer::IsCancelled() +{ + return fCancelled; +} + +void +USBTransfer::Do(int fRawFD) +{ + switch(fLibusbTransfer->type) + { + case LIBUSB_TRANSFER_TYPE_CONTROL: + { + struct libusb_control_setup* setup=(struct libusb_control_setup*)fLibusbTransfer->buffer; + usb_raw_command command; + command.control.request_type=setup->bmRequestType; + command.control.request=setup->bRequest; + command.control.value=setup->wValue; + command.control.index=setup->wIndex; + command.control.length=setup->wLength; + command.control.data=fLibusbTransfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; + if(fCancelled) + { + break; + } + if(ioctl(fRawFD,B_USB_RAW_COMMAND_CONTROL_TRANSFER,&command, + sizeof(command)) || command.control.status!=B_USB_RAW_STATUS_SUCCESS) { + fUsbiTransfer->transferred=-1; + usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed control transfer"); + break; + } + fUsbiTransfer->transferred=command.control.length; + } + break; + case LIBUSB_TRANSFER_TYPE_BULK: + case LIBUSB_TRANSFER_TYPE_INTERRUPT: + { + usb_raw_command command; + command.transfer.interface=fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint); + command.transfer.endpoint=fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint); + command.transfer.data=fLibusbTransfer->buffer; + command.transfer.length=fLibusbTransfer->length; + if(fCancelled) + { + break; + } + if(fLibusbTransfer->type==LIBUSB_TRANSFER_TYPE_BULK) + { + if(ioctl(fRawFD,B_USB_RAW_COMMAND_BULK_TRANSFER,&command, + sizeof(command)) || command.transfer.status!=B_USB_RAW_STATUS_SUCCESS) { + fUsbiTransfer->transferred=-1; + usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed bulk transfer"); + break; + } + } + else + { + if(ioctl(fRawFD,B_USB_RAW_COMMAND_INTERRUPT_TRANSFER,&command, + sizeof(command)) || command.transfer.status!=B_USB_RAW_STATUS_SUCCESS) { + fUsbiTransfer->transferred=-1; + usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed interrupt transfer"); + break; + } + } + fUsbiTransfer->transferred=command.transfer.length; + } + break; + // IsochronousTransfers not tested + case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: + { + usb_raw_command command; + command.isochronous.interface=fUSBDevice->EndpointToInterface(fLibusbTransfer->endpoint); + command.isochronous.endpoint=fUSBDevice->EndpointToIndex(fLibusbTransfer->endpoint); + command.isochronous.data=fLibusbTransfer->buffer; + command.isochronous.length=fLibusbTransfer->length; + command.isochronous.packet_count=fLibusbTransfer->num_iso_packets; + int i=0; + usb_iso_packet_descriptor *packetDescriptors = new usb_iso_packet_descriptor[fLibusbTransfer->num_iso_packets]; + for (i=0; inum_iso_packets; i++) + { + if((int16)(fLibusbTransfer->iso_packet_desc[i]).length!=(fLibusbTransfer->iso_packet_desc[i]).length) + { + fUsbiTransfer->transferred=-1; + usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed isochronous transfer"); + break; + } + packetDescriptors[i].request_length=(int16)(fLibusbTransfer->iso_packet_desc[i]).length; + } + if(inum_iso_packets) + { + break; // TODO Handle this error + } + command.isochronous.packet_descriptors=packetDescriptors; + if(fCancelled) + { + break; + } + if(ioctl(fRawFD,B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER,&command, + sizeof(command)) || command.isochronous.status!=B_USB_RAW_STATUS_SUCCESS) { + fUsbiTransfer->transferred=-1; + usbi_err(TRANSFER_CTX(fLibusbTransfer),"failed isochronous transfer"); + break; + } + for (i=0; inum_iso_packets; i++) + { + (fLibusbTransfer->iso_packet_desc[i]).actual_length=packetDescriptors[i].actual_length; + switch(packetDescriptors[i].status) + { + case B_OK: (fLibusbTransfer->iso_packet_desc[i]).status=LIBUSB_TRANSFER_COMPLETED; + break; + default: (fLibusbTransfer->iso_packet_desc[i]).status=LIBUSB_TRANSFER_ERROR; + break; + } + } + delete[] packetDescriptors; + // Do we put the length of transfer here, for isochronous transfers? + fUsbiTransfer->transferred=command.transfer.length; + } + break; + default: + usbi_err(TRANSFER_CTX(fLibusbTransfer),"Unknown type of transfer"); + } +} + +bool +USBDeviceHandle::InitCheck() +{ + return fInitCheck; +} + +status_t +USBDeviceHandle::TransfersThread(void* self) +{ + USBDeviceHandle* handle = (USBDeviceHandle*)self; + handle->TransfersWorker(); + return B_OK; +} + +void +USBDeviceHandle::TransfersWorker() +{ + while(true) + { + status_t status = acquire_sem(fTransfersSem); + if(status== B_BAD_SEM_ID) + break; + if(status == B_INTERRUPTED) + continue; + fTransfersLock.Lock(); + USBTransfer* fPendingTransfer= (USBTransfer*) fTransfers.RemoveItem((int32)0); + fTransfersLock.Unlock(); + fPendingTransfer->Do(fRawFD); + write(fEventPipes[1],&fPendingTransfer,sizeof(fPendingTransfer)); + } +} + +status_t +USBDeviceHandle::SubmitTransfer(struct usbi_transfer* itransfer) +{ + USBTransfer* transfer = new USBTransfer(itransfer,fUSBDevice); + *((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=transfer; + BAutolock locker(fTransfersLock); + fTransfers.AddItem(transfer); + release_sem(fTransfersSem); + return LIBUSB_SUCCESS; +} + +status_t +USBDeviceHandle::CancelTransfer(USBTransfer* transfer) +{ + transfer->SetCancelled(); + fTransfersLock.Lock(); + bool removed = fTransfers.RemoveItem(transfer); + fTransfersLock.Unlock(); + if(removed) + { + write(fEventPipes[1],&transfer,sizeof(transfer)); + } + return LIBUSB_SUCCESS; +} + +USBDeviceHandle::USBDeviceHandle(USBDevice* dev) + : + fTransfersThread(-1), + fUSBDevice(dev), + fClaimedInterfaces(0), + fInitCheck(false) +{ + fRawFD=open(dev->Location(), O_RDWR | O_CLOEXEC); + if(fRawFD < 0) + { + usbi_err(NULL,"failed to open device"); + return; + } + pipe(fEventPipes); + fcntl(fEventPipes[1], F_SETFD, O_NONBLOCK); + fTransfersSem = create_sem(0, "Transfers Queue Sem"); + fTransfersThread = spawn_thread(TransfersThread,"Transfer Worker",B_NORMAL_PRIORITY, this); + resume_thread(fTransfersThread); + fInitCheck = true; +} + +USBDeviceHandle::~USBDeviceHandle() +{ + if(fRawFD>0) + close(fRawFD); + for(int i=0; i<32; i++) + { + if(fClaimedInterfaces&(1<0) + close(fEventPipes[1]); + if(fEventPipes[0]>0) + close(fEventPipes[0]); + delete_sem(fTransfersSem); + if(fTransfersThread>0) + wait_for_thread(fTransfersThread, NULL); +} + +int +USBDeviceHandle::EventPipe(int index) const +{ + return fEventPipes[index]; +} + +int +USBDeviceHandle::ClaimInterface(int inumber) +{ + int status=fUSBDevice->ClaimInterface(inumber); + if(status==LIBUSB_SUCCESS) + { + fClaimedInterfaces|=(1<ReleaseInterface(inumber); + fClaimedInterfaces&=(!(1<CheckInterfacesFree(config); + if(config_index==LIBUSB_ERROR_BUSY || config_index==LIBUSB_ERROR_NOT_FOUND) + return config_index; + + usb_raw_command command; + command.config.config_index=config_index; + if(ioctl(fRawFD,B_USB_RAW_COMMAND_SET_CONFIGURATION,&command, + sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) { + return _errno_to_libusb(command.config.status); + } + fUSBDevice->SetActiveConfiguration(config_index); + return LIBUSB_SUCCESS; +} + +int +USBDeviceHandle::SetAltSetting(int inumber, int alt) +{ + usb_raw_command command; + command.alternate.config_index=fUSBDevice->ActiveConfigurationIndex(); + command.alternate.interface_index=inumber; + if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX,&command, + sizeof(command)) || command.alternate.status!=B_USB_RAW_STATUS_SUCCESS) { + usbi_err(NULL,"Error retrieving active alternate interface"); + return _errno_to_libusb(command.alternate.status); + } + if(command.alternate.alternate_info == alt) + { + usbi_dbg("Setting alternate interface successful"); + return LIBUSB_SUCCESS; + } + command.alternate.alternate_info = alt; + if(ioctl(fRawFD,B_USB_RAW_COMMAND_SET_ALT_INTERFACE,&command, //IF IOCTL FAILS DEVICE DISONNECTED PROBABLY + sizeof(command)) || command.alternate.status!=B_USB_RAW_STATUS_SUCCESS) { + usbi_err(NULL,"Error setting alternate interface"); + return _errno_to_libusb(command.alternate.status); + } + usbi_dbg("Setting alternate interface successful"); + return LIBUSB_SUCCESS; +} + + +USBDevice::USBDevice(const char * path) + : + fPath(NULL), + fActiveConfiguration(0), //0? + fConfigurationDescriptors(NULL), + fClaimedInterfaces(0), + fEndpointToIndex(NULL), + fEndpointToInterface(NULL), + fInitCheck(false) +{ + fPath=strdup(path); + Initialise(); +} + +USBDevice::~USBDevice() +{ + free(fPath); + if (fConfigurationDescriptors) + { + for(int i=0;iCountConfigurations()) + return NULL; + return (usb_configuration_descriptor*) fConfigurationDescriptors[index]; +} + +const usb_configuration_descriptor* +USBDevice::ActiveConfiguration() const +{ + return (usb_configuration_descriptor*) fConfigurationDescriptors[fActiveConfiguration]; +} + +int +USBDevice::ActiveConfigurationIndex() const +{ + return fActiveConfiguration; +} + +int USBDevice::ClaimInterface(int interface) +{ + if(interface>ActiveConfiguration()->number_interfaces) + { + return LIBUSB_ERROR_NOT_FOUND; + } + if((fClaimedInterfaces & (1< [fDeviceDescriptor.num_configurations]; + fEndpointToInterface = new(std::nothrow) map [fDeviceDescriptor.num_configurations]; + for( int i=0; i + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include +#include +#include + +#include "haiku_usb.h" + +USBRoster gUsbRoster; +int32 gInitCount = 0; + +static int +haiku_init(struct libusb_context* ctx) +{ + if (atomic_add(&gInitCount, 1) == 0) + { + return gUsbRoster.Start(); + } + return LIBUSB_SUCCESS; +} + +static void +haiku_exit(void) +{ + if (atomic_add(&gInitCount, -1) == 1) + gUsbRoster.Stop(); +} + +static int +haiku_open(struct libusb_device_handle *dev_handle) +{ + USBDevice* dev=*((USBDevice**)dev_handle->dev->os_priv); + USBDeviceHandle *handle=new(std::nothrow) USBDeviceHandle(dev); + if (handle == NULL) + return LIBUSB_ERROR_NO_MEM; + if (handle->InitCheck() == false) + { + delete handle; + return LIBUSB_ERROR_NO_DEVICE; + } + *((USBDeviceHandle**)dev_handle->os_priv)=handle; + return usbi_add_pollfd(HANDLE_CTX(dev_handle),handle->EventPipe(0), POLLIN); +} + +static void +haiku_close(struct libusb_device_handle *dev_handle) +{ + USBDeviceHandle * handle=*((USBDeviceHandle**)dev_handle->os_priv); + if(handle==NULL) + return; + usbi_remove_pollfd(HANDLE_CTX(dev_handle),handle->EventPipe(0)); + delete handle; + *((USBDeviceHandle**)dev_handle->os_priv)=NULL; +} + +static int +haiku_get_device_descriptor(struct libusb_device *device, unsigned char* buffer, int *host_endian) +{ + USBDevice *dev = *((USBDevice**)(device->os_priv)); + memcpy(buffer,dev->Descriptor(),DEVICE_DESC_LENGTH); + *host_endian=0; + return LIBUSB_SUCCESS; +} + +static int +haiku_get_active_config_descriptor(struct libusb_device *device, unsigned char *buffer, size_t len, int *host_endian) +{ + USBDevice *dev = *((USBDevice**)(device->os_priv)); + const usb_configuration_descriptor* act_config = dev->ActiveConfiguration(); + if(len>act_config->total_length) + { + return LIBUSB_ERROR_OVERFLOW; + } + memcpy(buffer,act_config,len); + *host_endian=0; + return LIBUSB_SUCCESS; +} + +static int +haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian) +{ + USBDevice *dev = *((USBDevice**)(device->os_priv)); + const usb_configuration_descriptor* config = dev->ConfigurationDescriptor(config_index); + if(config==NULL) + { + usbi_err(DEVICE_CTX(device),"failed getting configuration descriptor"); + return LIBUSB_ERROR_INVALID_PARAM; + } + if(len>config->total_length) + len=config->total_length; + memcpy(buffer,(unsigned char*)config,len); + *host_endian=0; + return len; +} + +static int +haiku_set_configuration(struct libusb_device_handle *dev_handle, int config) +{ + USBDeviceHandle * handle= *((USBDeviceHandle**)dev_handle->os_priv); + return handle->SetConfiguration(config); +} + +static int +haiku_claim_interface(struct libusb_device_handle *dev_handle, int interface_number) +{ + USBDeviceHandle * handle=*((USBDeviceHandle**)dev_handle->os_priv); + return handle->ClaimInterface(interface_number); +} + +static int +haiku_set_altsetting(struct libusb_device_handle* dev_handle, int interface_number, int altsetting) +{ + USBDeviceHandle* handle = *((USBDeviceHandle**)dev_handle->os_priv); + return handle->SetAltSetting(interface_number, altsetting); +} + +static int +haiku_release_interface(struct libusb_device_handle *dev_handle, int interface_number) +{ + USBDeviceHandle * handle=*((USBDeviceHandle**)dev_handle->os_priv); + haiku_set_altsetting(dev_handle,interface_number,0); + return handle->ReleaseInterface(interface_number); +} + +static int +haiku_submit_transfer(struct usbi_transfer * itransfer) +{ + struct libusb_transfer* fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + USBDeviceHandle * fDeviceHandle = *((USBDeviceHandle**)fLibusbTransfer->dev_handle->os_priv); + return fDeviceHandle->SubmitTransfer(itransfer); +} + +static int +haiku_cancel_transfer(struct usbi_transfer * itransfer) +{ + struct libusb_transfer* fLibusbTransfer = USBI_TRANSFER_TO_LIBUSB_TRANSFER(itransfer); + USBDeviceHandle * fDeviceHandle = *((USBDeviceHandle**)fLibusbTransfer->dev_handle->os_priv); + return fDeviceHandle->CancelTransfer(*((USBTransfer**)usbi_transfer_get_os_priv(itransfer))); +} + +static void +haiku_clear_transfer_priv(struct usbi_transfer * itransfer) +{ + USBTransfer* transfer=*((USBTransfer**)usbi_transfer_get_os_priv(itransfer)); + delete transfer; + *((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL; +} + +static int +haiku_handle_events(struct libusb_context* ctx, struct pollfd* fds, nfds_t nfds, int num_ready) +{ + USBTransfer *transfer; + for(int i=0;i0;i++) + { + struct pollfd *pollfd = &fds[i]; + if(!pollfd->revents) + continue; + + num_ready--; + read(pollfd->fd, &transfer, sizeof(transfer)); + struct usbi_transfer* itransfer=transfer->UsbiTransfer(); + usbi_mutex_lock(&itransfer->lock); + if(transfer->IsCancelled()) + { + delete transfer; + *((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL; + usbi_mutex_unlock(&itransfer->lock); + if (itransfer->transferred < 0) + itransfer->transferred = 0; + usbi_handle_transfer_cancellation(transfer->UsbiTransfer()); + continue; + } + libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED; + if(itransfer->transferred < 0) + { + usbi_err(ITRANSFER_CTX(itransfer),"error in transfer"); + status = LIBUSB_TRANSFER_ERROR; + itransfer->transferred=0; + } + delete transfer; + *((USBTransfer**)usbi_transfer_get_os_priv(itransfer))=NULL; + usbi_mutex_unlock(&itransfer->lock); + usbi_handle_transfer_completion(itransfer,status); + } + return LIBUSB_SUCCESS; +} + + +static int +haiku_clock_gettime(int clkid, struct timespec *tp) +{ + 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; +} + +const struct usbi_os_backend haiku_usb_raw_backend = { + /*.name =*/ "Haiku usbfs", + /*.caps =*/ 0, + /*.init =*/ haiku_init, + /*.exit =*/ haiku_exit, + /*.get_device_list =*/ NULL, + /*.hotplug_poll =*/ NULL, + /*.open =*/ haiku_open, + /*.close =*/ haiku_close, + /*.get_device_descriptor =*/ haiku_get_device_descriptor, + /*.get_active_config_descriptor =*/ haiku_get_active_config_descriptor, + /*.get_config_descriptor =*/ haiku_get_config_descriptor, + /*.get_config_descriptor_by_value =*/ NULL, + + + /*.get_configuration =*/ NULL, + /*.set_configuration =*/ haiku_set_configuration, + /*.claim_interface =*/ haiku_claim_interface, + /*.release_interface =*/ haiku_release_interface, + + /*.set_interface_altsetting =*/ haiku_set_altsetting, + /*.clear_halt =*/ NULL, + /*.reset_device =*/ NULL, + + /*.alloc_streams =*/ NULL, + /*.free_streams =*/ NULL, + + /*.kernel_driver_active =*/ NULL, + /*.detach_kernel_driver =*/ NULL, + /*.attach_kernel_driver =*/ NULL, + + /*.destroy_device =*/ NULL, + + /*.submit_transfer =*/ haiku_submit_transfer, + /*.cancel_transfer =*/ haiku_cancel_transfer, + /*.clear_transfer_priv =*/ haiku_clear_transfer_priv, + + /*.handle_events =*/ haiku_handle_events, + + /*.clock_gettime =*/ haiku_clock_gettime, + +#ifdef USBI_TIMERFD_AVAILABLE + /*.get_timerfd_clockid =*/ NULL, +#endif + + /*.device_priv_size =*/ sizeof(USBDevice*), + /*.device_handle_priv_size =*/ sizeof(USBDeviceHandle*), + /*.transfer_priv_size =*/ sizeof(USBTransfer*), + /*.add_iso_packet_size =*/ 0, +}; diff --git a/libusb/os/haiku/haiku_usb_raw.h b/libusb/os/haiku/haiku_usb_raw.h new file mode 100644 index 0000000..54112c2 --- /dev/null +++ b/libusb/os/haiku/haiku_usb_raw.h @@ -0,0 +1,180 @@ +/* + * Copyright 2006-2008, Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef _USB_RAW_H_ +#define _USB_RAW_H_ + +#include + +#define B_USB_RAW_PROTOCOL_VERSION 0x0015 +#define B_USB_RAW_ACTIVE_ALTERNATE 0xffffffff + +typedef enum { + B_USB_RAW_COMMAND_GET_VERSION = 0x1000, + + B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR = 0x2000, + B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, + B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR, + B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR, + B_USB_RAW_COMMAND_GET_STRING_DESCRIPTOR, + B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR, + B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, + B_USB_RAW_COMMAND_GET_ACTIVE_ALT_INTERFACE_INDEX, + B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, + B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, + B_USB_RAW_COMMAND_GET_GENERIC_DESCRIPTOR_ETC, + + B_USB_RAW_COMMAND_SET_CONFIGURATION = 0x3000, + B_USB_RAW_COMMAND_SET_FEATURE, + B_USB_RAW_COMMAND_CLEAR_FEATURE, + B_USB_RAW_COMMAND_GET_STATUS, + B_USB_RAW_COMMAND_GET_DESCRIPTOR, + B_USB_RAW_COMMAND_SET_ALT_INTERFACE, + + B_USB_RAW_COMMAND_CONTROL_TRANSFER = 0x4000, + B_USB_RAW_COMMAND_INTERRUPT_TRANSFER, + B_USB_RAW_COMMAND_BULK_TRANSFER, + B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER +} usb_raw_command_id; + + +typedef enum { + B_USB_RAW_STATUS_SUCCESS = 0, + + B_USB_RAW_STATUS_FAILED, + B_USB_RAW_STATUS_ABORTED, + B_USB_RAW_STATUS_STALLED, + B_USB_RAW_STATUS_CRC_ERROR, + B_USB_RAW_STATUS_TIMEOUT, + + B_USB_RAW_STATUS_INVALID_CONFIGURATION, + B_USB_RAW_STATUS_INVALID_INTERFACE, + B_USB_RAW_STATUS_INVALID_ENDPOINT, + B_USB_RAW_STATUS_INVALID_STRING, + + B_USB_RAW_STATUS_NO_MEMORY +} usb_raw_command_status; + + +typedef union { + struct { + status_t status; + } version; + + struct { + status_t status; + usb_device_descriptor *descriptor; + } device; + + struct { + status_t status; + usb_configuration_descriptor *descriptor; + uint32 config_index; + } config; + + struct { + status_t status; + uint32 alternate_info; + uint32 config_index; + uint32 interface_index; + } alternate; + + struct { + status_t status; + usb_interface_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + } interface; + + struct { + status_t status; + usb_interface_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + uint32 alternate_index; + } interface_etc; + + struct { + status_t status; + usb_endpoint_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + uint32 endpoint_index; + } endpoint; + + struct { + status_t status; + usb_endpoint_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + uint32 alternate_index; + uint32 endpoint_index; + } endpoint_etc; + + struct { + status_t status; + usb_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + uint32 generic_index; + size_t length; + } generic; + + struct { + status_t status; + usb_descriptor *descriptor; + uint32 config_index; + uint32 interface_index; + uint32 alternate_index; + uint32 generic_index; + size_t length; + } generic_etc; + + struct { + status_t status; + usb_string_descriptor *descriptor; + uint32 string_index; + size_t length; + } string; + + struct { + status_t status; + uint8 type; + uint8 index; + uint16 language_id; + void *data; + size_t length; + } descriptor; + + struct { + status_t status; + uint8 request_type; + uint8 request; + uint16 value; + uint16 index; + uint16 length; + void *data; + } control; + + struct { + status_t status; + uint32 interface; + uint32 endpoint; + void *data; + size_t length; + } transfer; + + struct { + status_t status; + uint32 interface; + uint32 endpoint; + void *data; + size_t length; + usb_iso_packet_descriptor *packet_descriptors; + uint32 packet_count; + } isochronous; +} usb_raw_command; + +#endif // _USB_RAW_H_ diff --git a/libusb/strerror.c b/libusb/strerror.c index 5b71585..a534041 100644 --- a/libusb/strerror.c +++ b/libusb/strerror.c @@ -22,6 +22,9 @@ #include #include #include +#if defined(HAVE_STRINGS_H) +#include +#endif #include "libusbi.h" diff --git a/libusb/version_nano.h b/libusb/version_nano.h index 4b584fa..4041786 100644 --- a/libusb/version_nano.h +++ b/libusb/version_nano.h @@ -1 +1 @@ -#define LIBUSB_NANO 10918 +#define LIBUSB_NANO 10919