haiku: Add Haiku support

This commit is contained in:
Akshay Jaggi
2014-09-24 22:46:17 +01:00
committed by Pete Batard
parent 12e9e35579
commit dc97425bb4
15 changed files with 1582 additions and 4 deletions
+8
View File
@@ -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
+26 -1
View File
@@ -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)
+12
View File
@@ -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
+2
View File
@@ -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
+1 -1
View File
@@ -54,7 +54,7 @@ typedef unsigned __int32 uint32_t;
#include <sys/types.h>
#endif
#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__)
#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) || defined(__HAIKU__)
#include <sys/time.h>
#endif
+14 -1
View File
@@ -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 <unistd.h>
#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
+5
View File
@@ -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
+8
View File
@@ -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
+378
View File
@@ -0,0 +1,378 @@
/*
* Copyright 2007-2008, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Michael Lotz <mmlr@mlotz.ch>
*/
#include "haiku_usb.h"
#include <cstdio>
#include <Directory.h>
#include <Entry.h>
#include <Looper.h>
#include <Messenger.h>
#include <Node.h>
#include <NodeMonitor.h>
#include <Path.h>
#include <cstring>
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;
}
+114
View File
@@ -0,0 +1,114 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.com>
*
* 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 <List.h>
#include <Locker.h>
#include <Autolock.h>
#include <USBKit.h>
#include <map>
#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<uint8,uint8> fConfigToIndex;
map<uint8,uint8>* fEndpointToIndex;
map<uint8,uint8>* 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;
};
+562
View File
@@ -0,0 +1,562 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.com>
*
* 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 <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <new>
#include <vector>
#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; i<fLibusbTransfer->num_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(i<fLibusbTransfer->num_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; i<fLibusbTransfer->num_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<<i))
ReleaseInterface(i);
}
if(fEventPipes[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<<inumber);
}
return status;
}
int
USBDeviceHandle::ReleaseInterface(int inumber)
{
fUSBDevice->ReleaseInterface(inumber);
fClaimedInterfaces&=(!(1<<inumber));
return LIBUSB_SUCCESS;
}
int
USBDeviceHandle::SetConfiguration(int config)
{
int config_index=fUSBDevice->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;i<fDeviceDescriptor.num_configurations;i++)
{
if (fConfigurationDescriptors[i])
delete fConfigurationDescriptors[i];
}
delete[] fConfigurationDescriptors;
}
if (fEndpointToIndex)
delete[] fEndpointToIndex;
if (fEndpointToInterface)
delete[] fEndpointToInterface;
}
bool
USBDevice::InitCheck()
{
return fInitCheck;
}
const char*
USBDevice::Location() const
{
return fPath;
}
uint8
USBDevice::CountConfigurations() const
{
return fDeviceDescriptor.num_configurations;
}
const usb_device_descriptor*
USBDevice::Descriptor() const
{
return &fDeviceDescriptor;
}
const usb_configuration_descriptor*
USBDevice::ConfigurationDescriptor(uint32 index) const
{
if(index>CountConfigurations())
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<<interface)) !=0 )
return LIBUSB_ERROR_BUSY;
fClaimedInterfaces|=(1<<interface);
return LIBUSB_SUCCESS;
}
int USBDevice::ReleaseInterface(int interface)
{
fClaimedInterfaces&=(!(1<<interface));
return LIBUSB_SUCCESS;
}
int
USBDevice::CheckInterfacesFree(int config)
{
if(fConfigToIndex.count(config)==0)
return LIBUSB_ERROR_NOT_FOUND;
if(fClaimedInterfaces==0)
return fConfigToIndex[(uint8)config];
return LIBUSB_ERROR_BUSY;
}
int
USBDevice::SetActiveConfiguration(int config_index)
{
fActiveConfiguration=config_index;
return LIBUSB_SUCCESS;
}
uint8
USBDevice::EndpointToIndex(uint8 address) const
{
return fEndpointToIndex[fActiveConfiguration][address];
}
uint8
USBDevice::EndpointToInterface(uint8 address) const
{
return fEndpointToInterface[fActiveConfiguration][address];
}
int
USBDevice::Initialise() //Do we need more error checking, etc? How to report?
{
int fRawFD=open(fPath, O_RDWR | O_CLOEXEC);
if(fRawFD < 0)
return B_ERROR;
usb_raw_command command;
command.device.descriptor = &fDeviceDescriptor;
if(ioctl(fRawFD, B_USB_RAW_COMMAND_GET_DEVICE_DESCRIPTOR, &command,
sizeof(command)) || command.device.status != B_USB_RAW_STATUS_SUCCESS) {
close(fRawFD);
return B_ERROR;
}
size_t size;
fConfigurationDescriptors = new(std::nothrow) unsigned char*[fDeviceDescriptor.num_configurations];
fEndpointToIndex = new(std::nothrow) map<uint8,uint8> [fDeviceDescriptor.num_configurations];
fEndpointToInterface = new(std::nothrow) map<uint8,uint8> [fDeviceDescriptor.num_configurations];
for( int i=0; i<fDeviceDescriptor.num_configurations; i++)
{
size=0;
usb_configuration_descriptor tmp_config;
command.config.descriptor = &tmp_config;
command.config.config_index = i;
if(ioctl(fRawFD, B_USB_RAW_COMMAND_GET_CONFIGURATION_DESCRIPTOR, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving configuration descriptor");
close(fRawFD);
return B_ERROR;
}
fConfigToIndex[tmp_config.configuration_value]=i;
fConfigurationDescriptors[i]=new(std::nothrow) unsigned char[tmp_config.total_length];
command.control.request_type=128;
command.control.request=6;
command.control.value=(2<<8)|i;
command.control.index=0;
command.control.length=tmp_config.total_length;
command.control.data=fConfigurationDescriptors[i];
if(ioctl(fRawFD,B_USB_RAW_COMMAND_CONTROL_TRANSFER,&command,
sizeof(command)) || command.control.status!=B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving full configuration descriptor");
close(fRawFD);
return B_ERROR;
}
for( int j=0;j<tmp_config.number_interfaces;j++)
{
command.alternate.config_index=i;
command.alternate.interface_index=j;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_ALT_INTERFACE_COUNT, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving number of alternate interfaces");
close(fRawFD);
return B_ERROR;
}
int num_alternate=command.alternate.alternate_info;
for( int k=0;k<num_alternate;k++)
{
usb_interface_descriptor tmp_interface;
command.interface_etc.config_index=i;
command.interface_etc.interface_index=j;
command.interface_etc.alternate_index=k;
command.interface_etc.descriptor=&tmp_interface;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_INTERFACE_DESCRIPTOR_ETC, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving interface descriptor");
close(fRawFD);
return B_ERROR;
}
for( int l=0;l<tmp_interface.num_endpoints;l++)
{
usb_endpoint_descriptor tmp_endpoint;
command.endpoint_etc.config_index=i;
command.endpoint_etc.interface_index=j;
command.endpoint_etc.alternate_index=k;
command.endpoint_etc.endpoint_index=l;
command.endpoint_etc.descriptor=&tmp_endpoint;
if(ioctl(fRawFD,B_USB_RAW_COMMAND_GET_ENDPOINT_DESCRIPTOR_ETC, &command,
sizeof(command)) || command.config.status != B_USB_RAW_STATUS_SUCCESS) {
usbi_err(NULL,"failed retrieving endpoint descriptor");
close(fRawFD);
return B_ERROR;
}
fEndpointToIndex[i][tmp_endpoint.endpoint_address]=l;
fEndpointToInterface[i][tmp_endpoint.endpoint_address]=j;
}
}
}
}
close(fRawFD);
fInitCheck = true;
return B_OK;
}
+268
View File
@@ -0,0 +1,268 @@
/*
* Haiku Backend for libusb
* Copyright © 2014 Akshay Jaggi <akshay1994.leo@gmail.com>
*
* 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 <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <new>
#include <vector>
#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;i<nfds && num_ready>0;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,
};
+180
View File
@@ -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 <USB3.h>
#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_
+3
View File
@@ -22,6 +22,9 @@
#include <locale.h>
#include <stdlib.h>
#include <string.h>
#if defined(HAVE_STRINGS_H)
#include <strings.h>
#endif
#include "libusbi.h"
+1 -1
View File
@@ -1 +1 @@
#define LIBUSB_NANO 10918
#define LIBUSB_NANO 10919