diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..faa890f --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +bdu +bdu.dSYM +payload.bin +payload.o +device_def.S +bootrom.bin diff --git a/Makefile b/Makefile index 59d4ca7..a06dc38 100644 --- a/Makefile +++ b/Makefile @@ -1,22 +1,41 @@ -CC = gcc -CFLAGS_OSX = -lusb-1.0 -framework CoreFoundation -framework IOKit -I./include -CFLAGS_LNX = -lusb-1.0 - -all: - @echo 'ERROR: no platform defined.' - @echo 'LINUX USERS: make linux' - @echo 'MAC OS X USERS: make macosx' - -macosx: - $(CC) bdu.c -o bdu $(CFLAGS_OSX) - - arm-elf-as -mthumb --fatal-warnings -o payload.o payload.S - arm-elf-objcopy -O binary payload.o payload.bin - rm payload.o - -linux: - $(CC) bdu.c -o bdu $(CFLAGS_LNX) - - arm-elf-as -mthumb --fatal-warnings -o payload.o payload.S - arm-elf-objcopy -O binary payload.o payload.bin - rm payload.o +CFLAGS = -lusb-1.0 -g + +ifeq ($(ARCH),mac) +CFLAGS += -framework CoreFoundation -framework IOKit -I include +endif + +ifeq ($(DEVICE),a4) +$(shell echo ".set RET_ADDR, 0x7ef" > device_def.S) +DEVICE_DEF = -DDEVICE_A4 +endif + +ifeq ($(DEVICE),3g) +$(shell echo ".set RET_ADDR, 0x8b7" > device_def.S) +DEVICE_DEF = -DDEVICE_3G +endif + +ifeq ($(DEVICE),3gs_new_bootrom) +$(shell echo ".set RET_ADDR, 0x8b7" > device_def.S) +DEVICE_DEF = -DDEVICE_3GS_NEW_BOOTROM +endif + +ifndef DEVICE_DEF +$(error You must define the device type by specifying DEVICE=< a4 | 3g | 3gs_new_bootrom > in your make invocation) +endif + + +all: bdu payload.bin + +.PHONY: clean + +clean: + rm -f payload.o payload.bin device_def.S bdu + +payload.o: payload.S device_def.S + ecc -target thumbv7-none-engeabihf -Werror -c -o $@ $< + +payload.bin: payload.o + ecc-objcopy -O binary $^ $@ + +bdu: bdu.c + $(CC) -o $@ $(CFLAGS) $(DEVICE_DEF) $^ diff --git a/README b/README index b315e47..efe82db 100644 --- a/README +++ b/README @@ -1,13 +1,12 @@ What to know about the Bootrom Dumper Utility (BDU) : - you need a mac or linux box to use it / build it - libusb > 1.0.8 required +- compatible with A4 devices (iPhone 4, iPod 4G, iPad, AppleTV 2) and older devices (iPhone 3Gs, iPod 3G) +- build it by running make with these arguments: + DEVICE=< a4 | 3g | 3gs_new_bootrom > + ARCH=mac if you're not using linux - execute it with root privileges (sudo ./bdu) -- by default compatible only with A4 devices : (iPhone 4, iPod 4G, iPad, AppleTV 2) - it's possible to extend the compatibility to older devices as well (iPhone 3Gs, iPod 3G) by changing: - * the offset to the call of usb_wait_for_image in payload.S - * exploit offsets in bdu.c - was too lazy to automate this stuff... -Happy Reverse Code Engeneering ! +Happy Reverse Code Engineering ! ~ pod2g diff --git a/bdu b/bdu deleted file mode 100755 index de89be3..0000000 Binary files a/bdu and /dev/null differ diff --git a/bdu.c b/bdu.c index 25223cd..a4f1bc2 100644 --- a/bdu.c +++ b/bdu.c @@ -15,14 +15,20 @@ #define LOADADDR 0x84000000 // A4: +#if defined(DEVICE_A4) #define EXPLOIT_LR 0x8403BF9C #define LOADADDR_SIZE 0x2C000 // iPod 3G: -//#define EXPLOIT_LR 0x84033F98 -//#define LOADADDR_SIZE 0x24000 +#elif defined(DEVICE_3G) +#define EXPLOIT_LR 0x84033F98 +#define LOADADDR_SIZE 0x24000 // iPhone 3Gs: -//#define EXPLOIT_LR 0x84033FA4 -//#define LOADADDR_SIZE 0x24000 +#elif defined(DEVICE_3GS_NEW_BOOTROM) +#define EXPLOIT_LR 0x84033FA4 +#define LOADADDR_SIZE 0x24000 +#else +#error No device type specified! +#endif #define VENDOR_ID 0x05AC #define WTF_MODE 0x1227 @@ -83,6 +89,7 @@ struct libusb_device_handle* usb_wait_device_connection(struct libusb_context* c sleep(2); usb_close(handle); handle = usb_init(context, WTF_MODE); + return handle; } int readfile(char *filename, void* buffer, unsigned int skip) { @@ -150,21 +157,22 @@ int main(int argc, char *argv[]) { #ifndef __APPLE__ printf("sent fake data to timeout: %X\n", libusb_control_transfer(handle, 0x21, 1, 0, 0, buf, 0x800, 10)); #else + #define DARWIN_CACHED_DEVICE(a) ((struct darwin_cached_device *) (((struct darwin_device_priv *)((a)->os_priv))->dev)) // pod2g: dirty hack for limera1n support. IOReturn kresult; - IOUSBDevRequest req; + IOUSBDevRequestTO req; bzero(&req, sizeof(req)); //struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)client->handle->os_priv; - struct darwin_device_priv *dpriv = (struct darwin_device_priv *)handle->dev->os_priv; + struct darwin_cached_device *dpriv = DARWIN_CACHED_DEVICE(handle->dev); req.bmRequestType = 0x21; req.bRequest = 1; req.wValue = OSSwapLittleToHostInt16 (0); req.wIndex = OSSwapLittleToHostInt16 (0); req.wLength = OSSwapLittleToHostInt16 (0x800); req.pData = buf + LIBUSB_CONTROL_SETUP_SIZE; - kresult = (*(dpriv->device))->DeviceRequestAsync(dpriv->device, &req, (IOAsyncCallback1) dummy_callback, NULL); + kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &req, (IOAsyncCallback1) dummy_callback, NULL); usleep(5 * 1000); - kresult = (*(dpriv->device))->USBDeviceAbortPipeZero (dpriv->device); + kresult = (*(dpriv->device))->USBDeviceAbortPipeZero(dpriv->device); #endif printf("sent exploit to heap overflow: %X\n", libusb_control_transfer(handle, 0x21, 2, 0, 0, buf, 0, 1000)); diff --git a/include/config.h b/include/config.h index 7d85163..492d43a 100644 --- a/include/config.h +++ b/include/config.h @@ -1,99 +1,28 @@ -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ +/* config.h. Manually generated for Xcode. */ /* Default visibility */ -//#define API_EXPORTED __attribute__((visibility("default"))) - -/* Debug message logging */ -/* #undef ENABLE_DEBUG_LOGGING */ +#define DEFAULT_VISIBILITY /**/ /* Message logging */ #define ENABLE_LOGGING 1 -/* Define to 1 if you have the header file. */ -#define HAVE_DLFCN_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `rt' library (-lrt). */ -/* #undef HAVE_LIBRT */ - -/* Define to 1 if you have the header file. */ -#define HAVE_MEMORY_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STDLIB_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_STRING_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -#define HAVE_UNISTD_H 1 +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define LT_OBJDIR ".libs/" +/* Define to 1 if you have the header file. */ +#define HAVE_POLL_H 1 -/* Define to 1 if your C compiler doesn't accept -c and -o together. */ -/* #undef NO_MINUS_C_MINUS_O */ +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TIME_H 1 /* Darwin backend */ -#define OS_DARWIN /**/ +#define OS_DARWIN 1 -/* Linux backend */ -/* #undef OS_LINUX */ +/* type of second poll() argument */ +#define POLL_NFDS_TYPE nfds_t -/* Name of package */ -#define PACKAGE "libusb" - -/* Define to the address where bug reports for this package should be sent. */ -#define PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define PACKAGE_NAME "libusb" - -/* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libusb 1.0.8" - -/* Define to the one symbol short name of this package. */ -#define PACKAGE_TARNAME "libusb" - -/* Define to the home page for this package. */ -#define PACKAGE_URL "" - -/* Define to the version of this package. */ -#define PACKAGE_VERSION "1.0.8" - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Backend handles timeout */ -#define USBI_OS_HANDLES_TIMEOUT /**/ - -/* timerfd headers available */ -/* #undef USBI_TIMERFD_AVAILABLE */ - -/* Version number of package */ -#define VERSION "1.0.8" +/* Use POSIX Threads */ +#define THREADS_POSIX 1 /* Use GNU extensions */ -#define _GNU_SOURCE /**/ - -/* Define to `__inline__' or `__inline' if that's what the C compiler - calls it, or to nothing if 'inline' is not supported under any name. */ -#ifndef __cplusplus -/* #undef inline */ -#endif \ No newline at end of file +#define _GNU_SOURCE 1 diff --git a/include/darwin_usb.h b/include/darwin_usb.h index a71d464..4cf28bf 100644 --- a/include/darwin_usb.h +++ b/include/darwin_usb.h @@ -1,6 +1,6 @@ /* * darwin backend for libusb 1.0 - * Copyright (C) 2008-2009 Nathan Hjelm + * Copyright © 2008-2013 Nathan Hjelm * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,7 +28,19 @@ #include /* IOUSBInterfaceInferface */ -#if defined (kIOUSBInterfaceInterfaceID300) +#if defined (kIOUSBInterfaceInterfaceID550) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 + +#define usb_interface_t IOUSBInterfaceInterface550 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID550 +#define InterfaceVersion 550 + +#elif defined (kIOUSBInterfaceInterfaceID500) + +#define usb_interface_t IOUSBInterfaceInterface500 +#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID500 +#define InterfaceVersion 500 + +#elif defined (kIOUSBInterfaceInterfaceID300) #define usb_interface_t IOUSBInterfaceInterface300 #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID300 @@ -46,24 +58,6 @@ #define InterfaceInterfaceID kIOUSBInterfaceInterfaceID220 #define InterfaceVersion 220 -#elif defined (kIOUSBInterfaceInterfaceID197) - -#define usb_interface_t IOUSBInterfaceInterface197 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID197 -#define InterfaceVersion 197 - -#elif defined (kIOUSBInterfaceInterfaceID190) - -#define usb_interface_t IOUSBInterfaceInterface190 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID190 -#define InterfaceVersion 190 - -#elif defined (kIOUSBInterfaceInterfaceID182) - -#define usb_interface_t IOUSBInterfaceInterface182 -#define InterfaceInterfaceID kIOUSBInterfaceInterfaceID182 -#define InterfaceVersion 182 - #else #error "IOUSBFamily is too old. Please upgrade your OS" @@ -71,7 +65,13 @@ #endif /* IOUSBDeviceInterface */ -#if defined (kIOUSBDeviceInterfaceID320) +#if defined (kIOUSBDeviceInterfaceID500) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 + +#define usb_device_t IOUSBDeviceInterface500 +#define DeviceInterfaceID kIOUSBDeviceInterfaceID500 +#define DeviceVersion 500 + +#elif defined (kIOUSBDeviceInterfaceID320) #define usb_device_t IOUSBDeviceInterface320 #define DeviceInterfaceID kIOUSBDeviceInterfaceID320 @@ -89,24 +89,11 @@ #define DeviceInterfaceID kIOUSBDeviceInterfaceID245 #define DeviceVersion 245 -#elif defined (kIOUSBDeviceInterfaceID197) - +#elif defined (kIOUSBDeviceInterfaceID220) #define usb_device_t IOUSBDeviceInterface197 #define DeviceInterfaceID kIOUSBDeviceInterfaceID197 #define DeviceVersion 197 -#elif defined (kIOUSBDeviceInterfaceID187) - -#define usb_device_t IOUSBDeviceInterface187 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID187 -#define DeviceVersion 187 - -#elif defined (kIOUSBDeviceInterfaceID182) - -#define usb_device_t IOUSBDeviceInterface182 -#define DeviceInterfaceID kIOUSBDeviceInterfaceID182 -#define DeviceVersion 182 - #else #error "IOUSBFamily is too old. Please upgrade your OS" @@ -121,47 +108,51 @@ typedef IOCFPlugInInterface *io_cf_plugin_ref_t; typedef IONotificationPortRef io_notification_port_t; /* private structures */ -struct darwin_device_priv { +struct darwin_cached_device { + struct list_head list; IOUSBDeviceDescriptor dev_descriptor; UInt32 location; + UInt64 parent_session; + UInt64 session; + UInt16 address; char sys_path[21]; usb_device_t **device; int open_count; - UInt8 first_config, active_config; + UInt8 first_config, active_config, port; + int can_enumerate; + int refcount; +}; + +struct darwin_device_priv { + struct darwin_cached_device *dev; }; struct darwin_device_handle_priv { int is_open; CFRunLoopSourceRef cfSource; - int fds[2]; - struct __darwin_interface { + struct darwin_interface { usb_interface_t **interface; uint8_t num_endpoints; CFRunLoopSourceRef cfSource; - uint8_t endpoint_addrs[USB_MAXENDPOINTS]; + uint64_t frames[256]; + uint8_t endpoint_addrs[USB_MAXENDPOINTS]; } interfaces[USB_MAXINTERFACES]; }; struct darwin_transfer_priv { /* Isoc */ IOUSBIsocFrame *isoc_framelist; + int num_iso_packets; /* Control */ -#if !defined (LIBUSB_NO_TIMEOUT_DEVICE) IOUSBDevRequestTO req; -#else - IOUSBDevRequest req; -#endif /* Bulk */ -}; -enum { - MESSAGE_DEVICE_GONE, - MESSAGE_ASYNC_IO_COMPLETE + /* Completion status */ + IOReturn result; + UInt32 size; }; - - #endif diff --git a/include/libusb.h b/include/libusb.h deleted file mode 100644 index 8dc3362..0000000 --- a/include/libusb.h +++ /dev/null @@ -1,1322 +0,0 @@ -/* - * Public libusb header file - * Copyright (C) 2007-2008 Daniel Drake - * Copyright (c) 2001 Johannes Erdfelt - * - * 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 - */ - -#ifndef __LIBUSB_H__ -#define __LIBUSB_H__ - -/* MSVC doesn't like inline, but does accept __inline ?? */ -#ifdef _MSC_VER -#define inline __inline -#endif - -#include -#include -#include -#include - -#if defined(__linux) || defined(__APPLE__) || defined(__CYGWIN__) -#include -#endif - -/* 'interface' might be defined as a macro on Windows, so we need to - * undefine it so as not to break the current libusb API, because - * libusb_config_descriptor has an 'interface' member - * As this can be problematic if you include windows.h after libusb.h - * in your sources, we force windows.h to be included first. */ -#if defined(_WIN32) || defined(__CYGWIN__) -#include -#if defined(interface) -#undef interface -#endif -#endif - -/** \def LIBUSB_CALL - * \ingroup misc - * libusb's Windows calling convention. - * - * Under Windows, the selection of available compilers and configurations - * means that, unlike other platforms, there is not one true calling - * convention (calling convention: the manner in which parameters are - * passed to funcions in the generated assembly code). - * - * Matching the Windows API itself, libusb uses the WINAPI convention (which - * translates to the stdcall convention) and guarantees that the - * library is compiled in this way. The public header file also includes - * appropriate annotations so that your own software will use the right - * convention, even if another convention is being used by default within - * your codebase. - * - * The one consideration that you must apply in your software is to mark - * all functions which you use as libusb callbacks with this LIBUSB_CALL - * annotation, so that they too get compiled for the correct calling - * convention. - * - * On non-Windows operating systems, this macro is defined as nothing. This - * means that you can apply it to your code without worrying about - * cross-platform compatibility. - */ -/* LIBUSB_CALL must be defined on both definition and declaration of libusb - * functions. You'd think that declaration would be enough, but cygwin will - * complain about conflicting types unless both are marked this way. - * The placement of this macro is important too; it must appear after the - * return type, before the function name. See internal documentation for - * API_EXPORTED. - */ -#if defined(_WIN32) || defined(__CYGWIN__) -#define LIBUSB_CALL WINAPI -#else -#define LIBUSB_CALL -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -/** \def libusb_cpu_to_le16 - * \ingroup misc - * Convert a 16-bit value from host-endian to little-endian format. On - * little endian systems, this function does nothing. On big endian systems, - * the bytes are swapped. - * \param x the host-endian value to convert - * \returns the value in little-endian byte order - */ -static inline uint16_t libusb_cpu_to_le16(const uint16_t x) -{ - union { - uint8_t b8[2]; - uint16_t b16; - } _tmp; - _tmp.b8[1] = x >> 8; - _tmp.b8[0] = x & 0xff; - return _tmp.b16; -} - -/** \def libusb_le16_to_cpu - * \ingroup misc - * Convert a 16-bit value from little-endian to host-endian format. On - * little endian systems, this function does nothing. On big endian systems, - * the bytes are swapped. - * \param x the little-endian value to convert - * \returns the value in host-endian byte order - */ -#define libusb_le16_to_cpu libusb_cpu_to_le16 - -/* standard USB stuff */ - -/** \ingroup desc - * Device and/or Interface Class codes */ -enum libusb_class_code { - /** In the context of a \ref libusb_device_descriptor "device descriptor", - * this bDeviceClass value indicates that each interface specifies its - * own class information and all interfaces operate independently. - */ - LIBUSB_CLASS_PER_INTERFACE = 0, - - /** Audio class */ - LIBUSB_CLASS_AUDIO = 1, - - /** Communications class */ - LIBUSB_CLASS_COMM = 2, - - /** Human Interface Device class */ - LIBUSB_CLASS_HID = 3, - - /** Printer dclass */ - LIBUSB_CLASS_PRINTER = 7, - - /** Picture transfer protocol class */ - LIBUSB_CLASS_PTP = 6, - - /** Mass storage class */ - LIBUSB_CLASS_MASS_STORAGE = 8, - - /** Hub class */ - LIBUSB_CLASS_HUB = 9, - - /** Data class */ - LIBUSB_CLASS_DATA = 10, - - /** Wireless class */ - LIBUSB_CLASS_WIRELESS = 0xe0, - - /** Application class */ - LIBUSB_CLASS_APPLICATION = 0xfe, - - /** Class is vendor-specific */ - LIBUSB_CLASS_VENDOR_SPEC = 0xff -}; - -/** \ingroup desc - * Descriptor types as defined by the USB specification. */ -enum libusb_descriptor_type { - /** Device descriptor. See libusb_device_descriptor. */ - LIBUSB_DT_DEVICE = 0x01, - - /** Configuration descriptor. See libusb_config_descriptor. */ - LIBUSB_DT_CONFIG = 0x02, - - /** String descriptor */ - LIBUSB_DT_STRING = 0x03, - - /** Interface descriptor. See libusb_interface_descriptor. */ - LIBUSB_DT_INTERFACE = 0x04, - - /** Endpoint descriptor. See libusb_endpoint_descriptor. */ - LIBUSB_DT_ENDPOINT = 0x05, - - /** HID descriptor */ - LIBUSB_DT_HID = 0x21, - - /** HID report descriptor */ - LIBUSB_DT_REPORT = 0x22, - - /** Physical descriptor */ - LIBUSB_DT_PHYSICAL = 0x23, - - /** Hub descriptor */ - LIBUSB_DT_HUB = 0x29 -}; - -/* Descriptor sizes per descriptor type */ -#define LIBUSB_DT_DEVICE_SIZE 18 -#define LIBUSB_DT_CONFIG_SIZE 9 -#define LIBUSB_DT_INTERFACE_SIZE 9 -#define LIBUSB_DT_ENDPOINT_SIZE 7 -#define LIBUSB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ -#define LIBUSB_DT_HUB_NONVAR_SIZE 7 - -#define LIBUSB_ENDPOINT_ADDRESS_MASK 0x0f /* in bEndpointAddress */ -#define LIBUSB_ENDPOINT_DIR_MASK 0x80 - -/** \ingroup desc - * Endpoint direction. Values for bit 7 of the - * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. - */ -enum libusb_endpoint_direction { - /** In: device-to-host */ - LIBUSB_ENDPOINT_IN = 0x80, - - /** Out: host-to-device */ - LIBUSB_ENDPOINT_OUT = 0x00 -}; - -#define LIBUSB_TRANSFER_TYPE_MASK 0x03 /* in bmAttributes */ - -/** \ingroup desc - * Endpoint transfer type. Values for bits 0:1 of the - * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. - */ -enum libusb_transfer_type { - /** Control endpoint */ - LIBUSB_TRANSFER_TYPE_CONTROL = 0, - - /** Isochronous endpoint */ - LIBUSB_TRANSFER_TYPE_ISOCHRONOUS = 1, - - /** Bulk endpoint */ - LIBUSB_TRANSFER_TYPE_BULK = 2, - - /** Interrupt endpoint */ - LIBUSB_TRANSFER_TYPE_INTERRUPT = 3 -}; - -/** \ingroup misc - * Standard requests, as defined in table 9-3 of the USB2 specifications */ -enum libusb_standard_request { - /** Request status of the specific recipient */ - LIBUSB_REQUEST_GET_STATUS = 0x00, - - /** Clear or disable a specific feature */ - LIBUSB_REQUEST_CLEAR_FEATURE = 0x01, - - /* 0x02 is reserved */ - - /** Set or enable a specific feature */ - LIBUSB_REQUEST_SET_FEATURE = 0x03, - - /* 0x04 is reserved */ - - /** Set device address for all future accesses */ - LIBUSB_REQUEST_SET_ADDRESS = 0x05, - - /** Get the specified descriptor */ - LIBUSB_REQUEST_GET_DESCRIPTOR = 0x06, - - /** Used to update existing descriptors or add new descriptors */ - LIBUSB_REQUEST_SET_DESCRIPTOR = 0x07, - - /** Get the current device configuration value */ - LIBUSB_REQUEST_GET_CONFIGURATION = 0x08, - - /** Set device configuration */ - LIBUSB_REQUEST_SET_CONFIGURATION = 0x09, - - /** Return the selected alternate setting for the specified interface */ - LIBUSB_REQUEST_GET_INTERFACE = 0x0A, - - /** Select an alternate interface for the specified interface */ - LIBUSB_REQUEST_SET_INTERFACE = 0x0B, - - /** Set then report an endpoint's synchronization frame */ - LIBUSB_REQUEST_SYNCH_FRAME = 0x0C -}; - -/** \ingroup misc - * Request type bits of the - * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control - * transfers. */ -enum libusb_request_type { - /** Standard */ - LIBUSB_REQUEST_TYPE_STANDARD = (0x00 << 5), - - /** Class */ - LIBUSB_REQUEST_TYPE_CLASS = (0x01 << 5), - - /** Vendor */ - LIBUSB_REQUEST_TYPE_VENDOR = (0x02 << 5), - - /** Reserved */ - LIBUSB_REQUEST_TYPE_RESERVED = (0x03 << 5) -}; - -/** \ingroup misc - * Recipient bits of the - * \ref libusb_control_setup::bmRequestType "bmRequestType" field in control - * transfers. Values 4 through 31 are reserved. */ -enum libusb_request_recipient { - /** Device */ - LIBUSB_RECIPIENT_DEVICE = 0x00, - - /** Interface */ - LIBUSB_RECIPIENT_INTERFACE = 0x01, - - /** Endpoint */ - LIBUSB_RECIPIENT_ENDPOINT = 0x02, - - /** Other */ - LIBUSB_RECIPIENT_OTHER = 0x03 -}; - -#define LIBUSB_ISO_SYNC_TYPE_MASK 0x0C - -/** \ingroup desc - * Synchronization type for isochronous endpoints. Values for bits 2:3 of the - * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in - * libusb_endpoint_descriptor. - */ -enum libusb_iso_sync_type { - /** No synchronization */ - LIBUSB_ISO_SYNC_TYPE_NONE = 0, - - /** Asynchronous */ - LIBUSB_ISO_SYNC_TYPE_ASYNC = 1, - - /** Adaptive */ - LIBUSB_ISO_SYNC_TYPE_ADAPTIVE = 2, - - /** Synchronous */ - LIBUSB_ISO_SYNC_TYPE_SYNC = 3 -}; - -#define LIBUSB_ISO_USAGE_TYPE_MASK 0x30 - -/** \ingroup desc - * Usage type for isochronous endpoints. Values for bits 4:5 of the - * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in - * libusb_endpoint_descriptor. - */ -enum libusb_iso_usage_type { - /** Data endpoint */ - LIBUSB_ISO_USAGE_TYPE_DATA = 0, - - /** Feedback endpoint */ - LIBUSB_ISO_USAGE_TYPE_FEEDBACK = 1, - - /** Implicit feedback Data endpoint */ - LIBUSB_ISO_USAGE_TYPE_IMPLICIT = 2 -}; - -/** \ingroup desc - * A structure representing the standard USB device descriptor. This - * descriptor is documented in section 9.6.1 of the USB 2.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_device_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this - * context. */ - uint8_t bDescriptorType; - - /** USB specification release number in binary-coded decimal. A value of - * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ - uint16_t bcdUSB; - - /** USB-IF class code for the device. See \ref libusb_class_code. */ - uint8_t bDeviceClass; - - /** USB-IF subclass code for the device, qualified by the bDeviceClass - * value */ - uint8_t bDeviceSubClass; - - /** USB-IF protocol code for the device, qualified by the bDeviceClass and - * bDeviceSubClass values */ - uint8_t bDeviceProtocol; - - /** Maximum packet size for endpoint 0 */ - uint8_t bMaxPacketSize0; - - /** USB-IF vendor ID */ - uint16_t idVendor; - - /** USB-IF product ID */ - uint16_t idProduct; - - /** Device release number in binary-coded decimal */ - uint16_t bcdDevice; - - /** Index of string descriptor describing manufacturer */ - uint8_t iManufacturer; - - /** Index of string descriptor describing product */ - uint8_t iProduct; - - /** Index of string descriptor containing device serial number */ - uint8_t iSerialNumber; - - /** Number of possible configurations */ - uint8_t bNumConfigurations; -}; - -/** \ingroup desc - * A structure representing the standard USB endpoint descriptor. This - * descriptor is documented in section 9.6.3 of the USB 2.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_endpoint_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in - * this context. */ - uint8_t bDescriptorType; - - /** The address of the endpoint described by this descriptor. Bits 0:3 are - * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, - * see \ref libusb_endpoint_direction. - */ - uint8_t bEndpointAddress; - - /** Attributes which apply to the endpoint when it is configured using - * the bConfigurationValue. Bits 0:1 determine the transfer type and - * correspond to \ref libusb_transfer_type. Bits 2:3 are only used for - * isochronous endpoints and correspond to \ref libusb_iso_sync_type. - * Bits 4:5 are also only used for isochronous endpoints and correspond to - * \ref libusb_iso_usage_type. Bits 6:7 are reserved. - */ - uint8_t bmAttributes; - - /** Maximum packet size this endpoint is capable of sending/receiving. */ - uint16_t wMaxPacketSize; - - /** Interval for polling endpoint for data transfers. */ - uint8_t bInterval; - - /** For audio devices only: the rate at which synchronization feedback - * is provided. */ - uint8_t bRefresh; - - /** For audio devices only: the address if the synch endpoint */ - uint8_t bSynchAddress; - - /** Extra descriptors. If libusb encounters unknown endpoint descriptors, - * it will store them here, should you wish to parse them. */ - const unsigned char *extra; - - /** Length of the extra descriptors, in bytes. */ - int extra_length; -}; - -/** \ingroup desc - * A structure representing the standard USB interface descriptor. This - * descriptor is documented in section 9.6.5 of the USB 2.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_interface_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE - * in this context. */ - uint8_t bDescriptorType; - - /** Number of this interface */ - uint8_t bInterfaceNumber; - - /** Value used to select this alternate setting for this interface */ - uint8_t bAlternateSetting; - - /** Number of endpoints used by this interface (excluding the control - * endpoint). */ - uint8_t bNumEndpoints; - - /** USB-IF class code for this interface. See \ref libusb_class_code. */ - uint8_t bInterfaceClass; - - /** USB-IF subclass code for this interface, qualified by the - * bInterfaceClass value */ - uint8_t bInterfaceSubClass; - - /** USB-IF protocol code for this interface, qualified by the - * bInterfaceClass and bInterfaceSubClass values */ - uint8_t bInterfaceProtocol; - - /** Index of string descriptor describing this interface */ - uint8_t iInterface; - - /** Array of endpoint descriptors. This length of this array is determined - * by the bNumEndpoints field. */ - const struct libusb_endpoint_descriptor *endpoint; - - /** Extra descriptors. If libusb encounters unknown interface descriptors, - * it will store them here, should you wish to parse them. */ - const unsigned char *extra; - - /** Length of the extra descriptors, in bytes. */ - int extra_length; -}; - -/** \ingroup desc - * A collection of alternate settings for a particular USB interface. - */ -struct libusb_interface { - /** Array of interface descriptors. The length of this array is determined - * by the num_altsetting field. */ - const struct libusb_interface_descriptor *altsetting; - - /** The number of alternate settings that belong to this interface */ - int num_altsetting; -}; - -/** \ingroup desc - * A structure representing the standard USB configuration descriptor. This - * descriptor is documented in section 9.6.3 of the USB 2.0 specification. - * All multiple-byte fields are represented in host-endian format. - */ -struct libusb_config_descriptor { - /** Size of this descriptor (in bytes) */ - uint8_t bLength; - - /** Descriptor type. Will have value - * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG - * in this context. */ - uint8_t bDescriptorType; - - /** Total length of data returned for this configuration */ - uint16_t wTotalLength; - - /** Number of interfaces supported by this configuration */ - uint8_t bNumInterfaces; - - /** Identifier value for this configuration */ - uint8_t bConfigurationValue; - - /** Index of string descriptor describing this configuration */ - uint8_t iConfiguration; - - /** Configuration characteristics */ - uint8_t bmAttributes; - - /** Maximum power consumption of the USB device from this bus in this - * configuration when the device is fully opreation. Expressed in units - * of 2 mA. */ - uint8_t MaxPower; - - /** Array of interfaces supported by this configuration. The length of - * this array is determined by the bNumInterfaces field. */ - const struct libusb_interface *interface; - - /** Extra descriptors. If libusb encounters unknown configuration - * descriptors, it will store them here, should you wish to parse them. */ - const unsigned char *extra; - - /** Length of the extra descriptors, in bytes. */ - int extra_length; -}; - -/** \ingroup asyncio - * Setup packet for control transfers. */ -struct libusb_control_setup { - /** Request type. Bits 0:4 determine recipient, see - * \ref libusb_request_recipient. Bits 5:6 determine type, see - * \ref libusb_request_type. Bit 7 determines data transfer direction, see - * \ref libusb_endpoint_direction. - */ - uint8_t bmRequestType; - - /** Request. If the type bits of bmRequestType are equal to - * \ref libusb_request_type::LIBUSB_REQUEST_TYPE_STANDARD - * "LIBUSB_REQUEST_TYPE_STANDARD" then this field refers to - * \ref libusb_standard_request. For other cases, use of this field is - * application-specific. */ - uint8_t bRequest; - - /** Value. Varies according to request */ - uint16_t wValue; - - /** Index. Varies according to request, typically used to pass an index - * or offset */ - uint16_t wIndex; - - /** Number of bytes to transfer */ - uint16_t wLength; -}; - -#define LIBUSB_CONTROL_SETUP_SIZE (sizeof(struct libusb_control_setup)) - -/* libusb */ - -struct libusb_context; -struct libusb_device; -struct libusb_device_handle; - -/** \ingroup lib - * Structure representing a libusb session. The concept of individual libusb - * sessions allows for your program to use two libraries (or dynamically - * load two modules) which both independently use libusb. This will prevent - * interference between the individual libusb users - for example - * libusb_set_debug() will not affect the other user of the library, and - * libusb_exit() will not destroy resources that the other user is still - * using. - * - * Sessions are created by libusb_init() and destroyed through libusb_exit(). - * If your application is guaranteed to only ever include a single libusb - * user (i.e. you), you do not have to worry about contexts: pass NULL in - * every function call where a context is required. The default context - * will be used. - * - * For more information, see \ref contexts. - */ -typedef struct libusb_context libusb_context; - -/** \ingroup dev - * Structure representing a USB device detected on the system. This is an - * opaque type for which you are only ever provided with a pointer, usually - * originating from libusb_get_device_list(). - * - * Certain operations can be performed on a device, but in order to do any - * I/O you will have to first obtain a device handle using libusb_open(). - * - * Devices are reference counted with libusb_device_ref() and - * libusb_device_unref(), and are freed when the reference count reaches 0. - * New devices presented by libusb_get_device_list() have a reference count of - * 1, and libusb_free_device_list() can optionally decrease the reference count - * on all devices in the list. libusb_open() adds another reference which is - * later destroyed by libusb_close(). - */ -typedef struct libusb_device libusb_device; - - -/** \ingroup dev - * Structure representing a handle on a USB device. This is an opaque type for - * which you are only ever provided with a pointer, usually originating from - * libusb_open(). - * - * A device handle is used to perform I/O and other operations. When finished - * with a device handle, you should call libusb_close(). - */ -typedef struct libusb_device_handle libusb_device_handle; - -/** \ingroup misc - * Error codes. Most libusb functions return 0 on success or one of these - * codes on failure. - * You can use libusb_strerror() to retrieve a short string description of - * a libusb_error enumeration value. - */ -enum libusb_error { - /** Success (no error) */ - LIBUSB_SUCCESS = 0, - - /** Input/output error */ - LIBUSB_ERROR_IO = -1, - - /** Invalid parameter */ - LIBUSB_ERROR_INVALID_PARAM = -2, - - /** Access denied (insufficient permissions) */ - LIBUSB_ERROR_ACCESS = -3, - - /** No such device (it may have been disconnected) */ - LIBUSB_ERROR_NO_DEVICE = -4, - - /** Entity not found */ - LIBUSB_ERROR_NOT_FOUND = -5, - - /** Resource busy */ - LIBUSB_ERROR_BUSY = -6, - - /** Operation timed out */ - LIBUSB_ERROR_TIMEOUT = -7, - - /** Overflow */ - LIBUSB_ERROR_OVERFLOW = -8, - - /** Pipe error */ - LIBUSB_ERROR_PIPE = -9, - - /** System call interrupted (perhaps due to signal) */ - LIBUSB_ERROR_INTERRUPTED = -10, - - /** Insufficient memory */ - LIBUSB_ERROR_NO_MEM = -11, - - /** Operation not supported or unimplemented on this platform */ - LIBUSB_ERROR_NOT_SUPPORTED = -12, - - /** Other error */ - LIBUSB_ERROR_OTHER = -99 - - /* IMPORTANT: when adding new values to this enum, remember to - update the libusb_strerror() function implementation! */ -}; - -/** \ingroup asyncio - * Transfer status codes */ -enum libusb_transfer_status { - /** Transfer completed without error. Note that this does not indicate - * that the entire amount of requested data was transferred. */ - LIBUSB_TRANSFER_COMPLETED, - - /** Transfer failed */ - LIBUSB_TRANSFER_ERROR, - - /** Transfer timed out */ - LIBUSB_TRANSFER_TIMED_OUT, - - /** Transfer was cancelled */ - LIBUSB_TRANSFER_CANCELLED, - - /** For bulk/interrupt endpoints: halt condition detected (endpoint - * stalled). For control endpoints: control request not supported. */ - LIBUSB_TRANSFER_STALL, - - /** Device was disconnected */ - LIBUSB_TRANSFER_NO_DEVICE, - - /** Device sent more data than requested */ - LIBUSB_TRANSFER_OVERFLOW -}; - -/** \ingroup asyncio - * libusb_transfer.flags values */ -enum libusb_transfer_flags { - /** Report short frames as errors */ - LIBUSB_TRANSFER_SHORT_NOT_OK = 1<<0, - - /** Automatically free() transfer buffer during libusb_free_transfer() */ - LIBUSB_TRANSFER_FREE_BUFFER = 1<<1, - - /** Automatically call libusb_free_transfer() after callback returns. - * If this flag is set, it is illegal to call libusb_free_transfer() - * from your transfer callback, as this will result in a double-free - * when this flag is acted upon. */ - LIBUSB_TRANSFER_FREE_TRANSFER = 1<<2 -}; - -/** \ingroup asyncio - * Isochronous packet descriptor. */ -struct libusb_iso_packet_descriptor { - /** Length of data to request in this packet */ - unsigned int length; - - /** Amount of data that was actually transferred */ - unsigned int actual_length; - - /** Status code for this packet */ - enum libusb_transfer_status status; -}; - -struct libusb_transfer; - -/** \ingroup asyncio - * Asynchronous transfer callback function type. When submitting asynchronous - * transfers, you pass a pointer to a callback function of this type via the - * \ref libusb_transfer::callback "callback" member of the libusb_transfer - * structure. libusb will call this function later, when the transfer has - * completed or failed. See \ref asyncio for more information. - * \param transfer The libusb_transfer struct the callback function is being - * notified about. - */ -typedef void (LIBUSB_CALL *libusb_transfer_cb_fn)(struct libusb_transfer *transfer); - -/** \ingroup asyncio - * The generic USB transfer structure. The user populates this structure and - * then submits it in order to request a transfer. After the transfer has - * completed, the library populates the transfer with the results and passes - * it back to the user. - */ -struct libusb_transfer { - /** Handle of the device that this transfer will be submitted to */ - libusb_device_handle *dev_handle; - - /** A bitwise OR combination of \ref libusb_transfer_flags. */ - uint8_t flags; - - /** Address of the endpoint where this transfer will be sent. */ - unsigned char endpoint; - - /** Type of the endpoint from \ref libusb_transfer_type */ - unsigned char type; - - /** Timeout for this transfer in millseconds. A value of 0 indicates no - * timeout. */ - unsigned int timeout; - - /** The status of the transfer. Read-only, and only for use within - * transfer callback function. - * - * If this is an isochronous transfer, this field may read COMPLETED even - * if there were errors in the frames. Use the - * \ref libusb_iso_packet_descriptor::status "status" field in each packet - * to determine if errors occurred. */ - enum libusb_transfer_status status; - - /** Length of the data buffer */ - int length; - - /** Actual length of data that was transferred. Read-only, and only for - * use within transfer callback function. Not valid for isochronous - * endpoint transfers. */ - int actual_length; - - /** Callback function. This will be invoked when the transfer completes, - * fails, or is cancelled. */ - libusb_transfer_cb_fn callback; - - /** User context data to pass to the callback function. */ - void *user_data; - - /** Data buffer */ - unsigned char *buffer; - - /** Number of isochronous packets. Only used for I/O with isochronous - * endpoints. */ - int num_iso_packets; - - /** Isochronous packet descriptors, for isochronous transfers only. */ - struct libusb_iso_packet_descriptor iso_packet_desc -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) - [] /* valid C99 code */ -#else - [0] /* non-standard, but usually working code */ -#endif - ; -}; - -int LIBUSB_CALL libusb_init(libusb_context **ctx); -void LIBUSB_CALL libusb_exit(libusb_context *ctx); -void LIBUSB_CALL libusb_set_debug(libusb_context *ctx, int level); -const char * LIBUSB_CALL libusb_strerror(enum libusb_error errcode); - -ssize_t LIBUSB_CALL libusb_get_device_list(libusb_context *ctx, - libusb_device ***list); -void LIBUSB_CALL libusb_free_device_list(libusb_device **list, - int unref_devices); -libusb_device * LIBUSB_CALL libusb_ref_device(libusb_device *dev); -void LIBUSB_CALL libusb_unref_device(libusb_device *dev); - -int LIBUSB_CALL libusb_get_configuration(libusb_device_handle *dev, - int *config); -int LIBUSB_CALL libusb_get_device_descriptor(libusb_device *dev, - struct libusb_device_descriptor *desc); -int LIBUSB_CALL libusb_get_active_config_descriptor(libusb_device *dev, - struct libusb_config_descriptor **config); -int LIBUSB_CALL libusb_get_config_descriptor(libusb_device *dev, - uint8_t config_index, struct libusb_config_descriptor **config); -int LIBUSB_CALL libusb_get_config_descriptor_by_value(libusb_device *dev, - uint8_t bConfigurationValue, struct libusb_config_descriptor **config); -void LIBUSB_CALL libusb_free_config_descriptor( - struct libusb_config_descriptor *config); -uint8_t LIBUSB_CALL libusb_get_bus_number(libusb_device *dev); -uint8_t LIBUSB_CALL libusb_get_device_address(libusb_device *dev); -int LIBUSB_CALL libusb_get_max_packet_size(libusb_device *dev, - unsigned char endpoint); -int LIBUSB_CALL libusb_get_max_iso_packet_size(libusb_device *dev, - unsigned char endpoint); - -int LIBUSB_CALL libusb_open(libusb_device *dev, libusb_device_handle **handle); -void LIBUSB_CALL libusb_close(libusb_device_handle *dev_handle); -libusb_device * LIBUSB_CALL libusb_get_device(libusb_device_handle *dev_handle); - -int LIBUSB_CALL libusb_set_configuration(libusb_device_handle *dev, - int configuration); -int LIBUSB_CALL libusb_claim_interface(libusb_device_handle *dev, - int interface_number); -int LIBUSB_CALL libusb_release_interface(libusb_device_handle *dev, - int interface_number); - -libusb_device_handle * LIBUSB_CALL libusb_open_device_with_vid_pid( - libusb_context *ctx, uint16_t vendor_id, uint16_t product_id); - -int LIBUSB_CALL libusb_set_interface_alt_setting(libusb_device_handle *dev, - int interface_number, int alternate_setting); -int LIBUSB_CALL libusb_clear_halt(libusb_device_handle *dev, - unsigned char endpoint); -int LIBUSB_CALL libusb_reset_device(libusb_device_handle *dev); - -int LIBUSB_CALL libusb_kernel_driver_active(libusb_device_handle *dev, - int interface_number); -int LIBUSB_CALL libusb_detach_kernel_driver(libusb_device_handle *dev, - int interface_number); -int LIBUSB_CALL libusb_attach_kernel_driver(libusb_device_handle *dev, - int interface_number); - -/* async I/O */ - -/** \ingroup asyncio - * Get the data section of a control transfer. This convenience function is here - * to remind you that the data does not start until 8 bytes into the actual - * buffer, as the setup packet comes first. - * - * Calling this function only makes sense from a transfer callback function, - * or situations where you have already allocated a suitably sized buffer at - * transfer->buffer. - * - * \param transfer a transfer - * \returns pointer to the first byte of the data section - */ -static inline unsigned char *libusb_control_transfer_get_data( - struct libusb_transfer *transfer) -{ - return transfer->buffer + LIBUSB_CONTROL_SETUP_SIZE; -} - -/** \ingroup asyncio - * Get the control setup packet of a control transfer. This convenience - * function is here to remind you that the control setup occupies the first - * 8 bytes of the transfer data buffer. - * - * Calling this function only makes sense from a transfer callback function, - * or situations where you have already allocated a suitably sized buffer at - * transfer->buffer. - * - * \param transfer a transfer - * \returns a casted pointer to the start of the transfer data buffer - */ -static inline struct libusb_control_setup *libusb_control_transfer_get_setup( - struct libusb_transfer *transfer) -{ - return (struct libusb_control_setup *) transfer->buffer; -} - -/** \ingroup asyncio - * Helper function to populate the setup packet (first 8 bytes of the data - * buffer) for a control transfer. The wIndex, wValue and wLength values should - * be given in host-endian byte order. - * - * \param buffer buffer to output the setup packet into - * \param bmRequestType see the - * \ref libusb_control_setup::bmRequestType "bmRequestType" field of - * \ref libusb_control_setup - * \param bRequest see the - * \ref libusb_control_setup::bRequest "bRequest" field of - * \ref libusb_control_setup - * \param wValue see the - * \ref libusb_control_setup::wValue "wValue" field of - * \ref libusb_control_setup - * \param wIndex see the - * \ref libusb_control_setup::wIndex "wIndex" field of - * \ref libusb_control_setup - * \param wLength see the - * \ref libusb_control_setup::wLength "wLength" field of - * \ref libusb_control_setup - */ -static inline void libusb_fill_control_setup(unsigned char *buffer, - uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, - uint16_t wLength) -{ - struct libusb_control_setup *setup = (struct libusb_control_setup *) buffer; - setup->bmRequestType = bmRequestType; - setup->bRequest = bRequest; - setup->wValue = libusb_cpu_to_le16(wValue); - setup->wIndex = libusb_cpu_to_le16(wIndex); - setup->wLength = libusb_cpu_to_le16(wLength); -} - -struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(int iso_packets); -int LIBUSB_CALL libusb_submit_transfer(struct libusb_transfer *transfer); -int LIBUSB_CALL libusb_cancel_transfer(struct libusb_transfer *transfer); -void LIBUSB_CALL libusb_free_transfer(struct libusb_transfer *transfer); - -/** \ingroup asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for a control transfer. - * - * If you pass a transfer buffer to this function, the first 8 bytes will - * be interpreted as a control setup packet, and the wLength field will be - * used to automatically populate the \ref libusb_transfer::length "length" - * field of the transfer. Therefore the recommended approach is: - * -# Allocate a suitably sized data buffer (including space for control setup) - * -# Call libusb_fill_control_setup() - * -# If this is a host-to-device transfer with a data stage, put the data - * in place after the setup packet - * -# Call this function - * -# Call libusb_submit_transfer() - * - * It is also legal to pass a NULL buffer to this function, in which case this - * function will not attempt to populate the length field. Remember that you - * must then populate the buffer and length fields later. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param buffer data buffer. If provided, this function will interpret the - * first 8 bytes as a setup packet and infer the transfer length from that. - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_control_transfer( - struct libusb_transfer *transfer, libusb_device_handle *dev_handle, - unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data, - unsigned int timeout) -{ - struct libusb_control_setup *setup = (struct libusb_control_setup *) buffer; - transfer->dev_handle = dev_handle; - transfer->endpoint = 0; - transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL; - transfer->timeout = timeout; - transfer->buffer = buffer; - if (setup) - transfer->length = LIBUSB_CONTROL_SETUP_SIZE - + libusb_le16_to_cpu(setup->wLength); - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for a bulk transfer. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param endpoint address of the endpoint where this transfer will be sent - * \param buffer data buffer - * \param length length of data buffer - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_bulk_transfer(struct libusb_transfer *transfer, - libusb_device_handle *dev_handle, unsigned char endpoint, - unsigned char *buffer, int length, libusb_transfer_cb_fn callback, - void *user_data, unsigned int timeout) -{ - transfer->dev_handle = dev_handle; - transfer->endpoint = endpoint; - transfer->type = LIBUSB_TRANSFER_TYPE_BULK; - transfer->timeout = timeout; - transfer->buffer = buffer; - transfer->length = length; - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for an interrupt transfer. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param endpoint address of the endpoint where this transfer will be sent - * \param buffer data buffer - * \param length length of data buffer - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_interrupt_transfer( - struct libusb_transfer *transfer, libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *buffer, int length, - libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) -{ - transfer->dev_handle = dev_handle; - transfer->endpoint = endpoint; - transfer->type = LIBUSB_TRANSFER_TYPE_INTERRUPT; - transfer->timeout = timeout; - transfer->buffer = buffer; - transfer->length = length; - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup asyncio - * Helper function to populate the required \ref libusb_transfer fields - * for an isochronous transfer. - * - * \param transfer the transfer to populate - * \param dev_handle handle of the device that will handle the transfer - * \param endpoint address of the endpoint where this transfer will be sent - * \param buffer data buffer - * \param length length of data buffer - * \param num_iso_packets the number of isochronous packets - * \param callback callback function to be invoked on transfer completion - * \param user_data user data to pass to callback function - * \param timeout timeout for the transfer in milliseconds - */ -static inline void libusb_fill_iso_transfer(struct libusb_transfer *transfer, - libusb_device_handle *dev_handle, unsigned char endpoint, - unsigned char *buffer, int length, int num_iso_packets, - libusb_transfer_cb_fn callback, void *user_data, unsigned int timeout) -{ - transfer->dev_handle = dev_handle; - transfer->endpoint = endpoint; - transfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS; - transfer->timeout = timeout; - transfer->buffer = buffer; - transfer->length = length; - transfer->num_iso_packets = num_iso_packets; - transfer->user_data = user_data; - transfer->callback = callback; -} - -/** \ingroup asyncio - * Convenience function to set the length of all packets in an isochronous - * transfer, based on the num_iso_packets field in the transfer structure. - * - * \param transfer a transfer - * \param length the length to set in each isochronous packet descriptor - * \see libusb_get_max_packet_size() - */ -static inline void libusb_set_iso_packet_lengths( - struct libusb_transfer *transfer, unsigned int length) -{ - int i; - for (i = 0; i < transfer->num_iso_packets; i++) - transfer->iso_packet_desc[i].length = length; -} - -/** \ingroup asyncio - * Convenience function to locate the position of an isochronous packet - * within the buffer of an isochronous transfer. - * - * This is a thorough function which loops through all preceding packets, - * accumulating their lengths to find the position of the specified packet. - * Typically you will assign equal lengths to each packet in the transfer, - * and hence the above method is sub-optimal. You may wish to use - * libusb_get_iso_packet_buffer_simple() instead. - * - * \param transfer a transfer - * \param packet the packet to return the address of - * \returns the base address of the packet buffer inside the transfer buffer, - * or NULL if the packet does not exist. - * \see libusb_get_iso_packet_buffer_simple() - */ -static inline unsigned char *libusb_get_iso_packet_buffer( - struct libusb_transfer *transfer, unsigned int packet) -{ - int i; - size_t offset = 0; - int _packet; - - /* oops..slight bug in the API. packet is an unsigned int, but we use - * signed integers almost everywhere else. range-check and convert to - * signed to avoid compiler warnings. FIXME for libusb-2. */ - if (packet > INT_MAX) - return NULL; - _packet = packet; - - if (_packet >= transfer->num_iso_packets) - return NULL; - - for (i = 0; i < _packet; i++) - offset += transfer->iso_packet_desc[i].length; - - return transfer->buffer + offset; -} - -/** \ingroup asyncio - * Convenience function to locate the position of an isochronous packet - * within the buffer of an isochronous transfer, for transfers where each - * packet is of identical size. - * - * This function relies on the assumption that every packet within the transfer - * is of identical size to the first packet. Calculating the location of - * the packet buffer is then just a simple calculation: - * buffer + (packet_size * packet) - * - * Do not use this function on transfers other than those that have identical - * packet lengths for each packet. - * - * \param transfer a transfer - * \param packet the packet to return the address of - * \returns the base address of the packet buffer inside the transfer buffer, - * or NULL if the packet does not exist. - * \see libusb_get_iso_packet_buffer() - */ -static inline unsigned char *libusb_get_iso_packet_buffer_simple( - struct libusb_transfer *transfer, unsigned int packet) -{ - int _packet; - - /* oops..slight bug in the API. packet is an unsigned int, but we use - * signed integers almost everywhere else. range-check and convert to - * signed to avoid compiler warnings. FIXME for libusb-2. */ - if (packet > INT_MAX) - return NULL; - _packet = packet; - - if (_packet >= transfer->num_iso_packets) - return NULL; - - return transfer->buffer + (transfer->iso_packet_desc[0].length * _packet); -} - -/* sync I/O */ - -int LIBUSB_CALL libusb_control_transfer(libusb_device_handle *dev_handle, - uint8_t request_type, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, - unsigned char *data, uint16_t wLength, unsigned int timeout); - -int LIBUSB_CALL libusb_bulk_transfer(libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *data, int length, - int *actual_length, unsigned int timeout); - -int LIBUSB_CALL libusb_interrupt_transfer(libusb_device_handle *dev_handle, - unsigned char endpoint, unsigned char *data, int length, - int *actual_length, unsigned int timeout); - -/** \ingroup desc - * Retrieve a descriptor from the default control pipe. - * This is a convenience function which formulates the appropriate control - * message to retrieve the descriptor. - * - * \param dev a device handle - * \param desc_type the descriptor type, see \ref libusb_descriptor_type - * \param desc_index the index of the descriptor to retrieve - * \param data output buffer for descriptor - * \param length size of data buffer - * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure - */ -static inline int libusb_get_descriptor(libusb_device_handle *dev, - uint8_t desc_type, uint8_t desc_index, unsigned char *data, int length) -{ - return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_DESCRIPTOR, (desc_type << 8) | desc_index, 0, data, - (uint16_t) length, 1000); -} - -/** \ingroup desc - * Retrieve a descriptor from a device. - * This is a convenience function which formulates the appropriate control - * message to retrieve the descriptor. The string returned is Unicode, as - * detailed in the USB specifications. - * - * \param dev a device handle - * \param desc_index the index of the descriptor to retrieve - * \param langid the language ID for the string descriptor - * \param data output buffer for descriptor - * \param length size of data buffer - * \returns number of bytes returned in data, or LIBUSB_ERROR code on failure - * \see libusb_get_string_descriptor_ascii() - */ -static inline int libusb_get_string_descriptor(libusb_device_handle *dev, - uint8_t desc_index, uint16_t langid, unsigned char *data, int length) -{ - return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN, - LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | desc_index, - langid, data, (uint16_t) length, 1000); -} - -int LIBUSB_CALL libusb_get_string_descriptor_ascii(libusb_device_handle *dev, - uint8_t desc_index, unsigned char *data, int length); - -/* polling and timeouts */ - -int LIBUSB_CALL libusb_try_lock_events(libusb_context *ctx); -void LIBUSB_CALL libusb_lock_events(libusb_context *ctx); -void LIBUSB_CALL libusb_unlock_events(libusb_context *ctx); -int LIBUSB_CALL libusb_event_handling_ok(libusb_context *ctx); -int LIBUSB_CALL libusb_event_handler_active(libusb_context *ctx); -void LIBUSB_CALL libusb_lock_event_waiters(libusb_context *ctx); -void LIBUSB_CALL libusb_unlock_event_waiters(libusb_context *ctx); -int LIBUSB_CALL libusb_wait_for_event(libusb_context *ctx, struct timeval *tv); - -int LIBUSB_CALL libusb_handle_events_timeout(libusb_context *ctx, - struct timeval *tv); -int LIBUSB_CALL libusb_handle_events(libusb_context *ctx); -int LIBUSB_CALL libusb_handle_events_locked(libusb_context *ctx, - struct timeval *tv); -int LIBUSB_CALL libusb_pollfds_handle_timeouts(libusb_context *ctx); -int LIBUSB_CALL libusb_get_next_timeout(libusb_context *ctx, - struct timeval *tv); - -/** \ingroup poll - * File descriptor for polling - */ -struct libusb_pollfd { - /** Numeric file descriptor */ - int fd; - - /** Event flags to poll for from . POLLIN indicates that you - * should monitor this file descriptor for becoming ready to read from, - * and POLLOUT indicates that you should monitor this file descriptor for - * nonblocking write readiness. */ - short events; -}; - -/** \ingroup poll - * Callback function, invoked when a new file descriptor should be added - * to the set of file descriptors monitored for events. - * \param fd the new file descriptor - * \param events events to monitor for, see \ref libusb_pollfd for a - * description - * \param user_data User data pointer specified in - * libusb_set_pollfd_notifiers() call - * \see libusb_set_pollfd_notifiers() - */ -typedef void (LIBUSB_CALL *libusb_pollfd_added_cb)(int fd, short events, - void *user_data); - -/** \ingroup poll - * Callback function, invoked when a file descriptor should be removed from - * the set of file descriptors being monitored for events. After returning - * from this callback, do not use that file descriptor again. - * \param fd the file descriptor to stop monitoring - * \param user_data User data pointer specified in - * libusb_set_pollfd_notifiers() call - * \see libusb_set_pollfd_notifiers() - */ -typedef void (LIBUSB_CALL *libusb_pollfd_removed_cb)(int fd, void *user_data); - -const struct libusb_pollfd ** LIBUSB_CALL libusb_get_pollfds( - libusb_context *ctx); -void LIBUSB_CALL libusb_set_pollfd_notifiers(libusb_context *ctx, - libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb removed_cb, - void *user_data); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/include/libusbi.h b/include/libusbi.h index 577e861..4d13432 100644 --- a/include/libusbi.h +++ b/include/libusbi.h @@ -1,7 +1,7 @@ /* * Internal header for libusb - * Copyright (C) 2007-2009 Daniel Drake - * Copyright (c) 2001 Johannes Erdfelt + * Copyright © 2007-2009 Daniel Drake + * Copyright © 2001 Johannes Erdfelt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,17 +18,26 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __LIBUSBI_H__ -#define __LIBUSBI_H__ +#ifndef LIBUSBI_H +#define LIBUSBI_H -#include "config.h" +#include + +#include #include #include #include +#include +#ifdef HAVE_POLL_H +#include +#endif +#ifdef HAVE_MISSING_H +#include +#endif -#include "libusb.h" -#include "threads_posix.h" +#include +#include "version.h" /* Inside the libusb code, mark all public functions as follows: * return_type API_EXPORTED function_name(params) { ... } @@ -39,29 +48,52 @@ */ #define API_EXPORTED LIBUSB_CALL DEFAULT_VISIBILITY +#ifdef __cplusplus +extern "C" { +#endif + #define DEVICE_DESC_LENGTH 18 #define USB_MAXENDPOINTS 32 #define USB_MAXINTERFACES 32 #define USB_MAXCONFIG 8 +/* Backend specific capabilities */ +#define USBI_CAP_HAS_HID_ACCESS 0x00010000 +#define USBI_CAP_SUPPORTS_DETACH_KERNEL_DRIVER 0x00020000 + +/* Maximum number of bytes in a log line */ +#define USBI_MAX_LOG_LEN 1024 +/* Terminator for log lines */ +#define USBI_LOG_LINE_END "\n" + +/* The following is used to silence warnings for unused variables */ +#define UNUSED(var) do { (void)(var); } while(0) + +#if !defined(ARRAYSIZE) +#define ARRAYSIZE(array) (sizeof(array)/sizeof(array[0])) +#endif + struct list_head { struct list_head *prev, *next; }; /* Get an entry from the list - * ptr - the address of this list_head element in "type" - * type - the data type that contains "member" - * member - the list_head element in "type" + * ptr - the address of this list_head element in "type" + * type - the data type that contains "member" + * member - the list_head element in "type" */ #define list_entry(ptr, type, member) \ - ((type *)((uintptr_t)(ptr) - (uintptr_t)(&((type *)0L)->member))) + ((type *)((uintptr_t)(ptr) - (uintptr_t)offsetof(type, member))) + +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) /* Get each entry from a list - * pos - A structure pointer has a "member" element - * head - list head - * member - the list_head element in "pos" - * type - the type of the first parameter + * pos - A structure pointer has a "member" element + * head - list head + * member - the list_head element in "pos" + * type - the type of the first parameter */ #define list_for_each_entry(pos, head, member, type) \ for (pos = list_entry((head)->next, type, member); \ @@ -104,49 +136,60 @@ static inline void list_del(struct list_head *entry) { entry->next->prev = entry->prev; entry->prev->next = entry->next; + entry->next = entry->prev = NULL; +} + +static inline void *usbi_reallocf(void *ptr, size_t size) +{ + void *ret = realloc(ptr, size); + if (!ret) + free(ptr); + return ret; } #define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) + 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) -enum usbi_log_level { - LOG_LEVEL_DEBUG, - LOG_LEVEL_INFO, - LOG_LEVEL_WARNING, - LOG_LEVEL_ERROR, -}; +/* Some platforms don't have this define */ +#ifndef TIMESPEC_TO_TIMEVAL +#define TIMESPEC_TO_TIMEVAL(tv, ts) \ + do { \ + (tv)->tv_sec = (ts)->tv_sec; \ + (tv)->tv_usec = (ts)->tv_nsec / 1000; \ + } while (0) +#endif -void usbi_log(struct libusb_context *ctx, enum usbi_log_level level, +void usbi_log(struct libusb_context *ctx, enum libusb_log_level level, const char *function, const char *format, ...); -#if !defined(_MSC_VER) || _MSC_VER > 1200 +void usbi_log_v(struct libusb_context *ctx, enum libusb_log_level level, + const char *function, const char *format, va_list args); + +#if !defined(_MSC_VER) || _MSC_VER >= 1400 #ifdef ENABLE_LOGGING #define _usbi_log(ctx, level, ...) usbi_log(ctx, level, __FUNCTION__, __VA_ARGS__) +#define usbi_dbg(...) _usbi_log(NULL, LIBUSB_LOG_LEVEL_DEBUG, __VA_ARGS__) #else -#define _usbi_log(ctx, level, ...) +#define _usbi_log(ctx, level, ...) do { (void)(ctx); } while(0) +#define usbi_dbg(...) do {} while(0) #endif -#ifdef ENABLE_DEBUG_LOGGING -#define usbi_dbg(...) _usbi_log(NULL, LOG_LEVEL_DEBUG, __VA_ARGS__) -#else -#define usbi_dbg(...) -#endif - -#define usbi_info(ctx, ...) _usbi_log(ctx, LOG_LEVEL_INFO, __VA_ARGS__) -#define usbi_warn(ctx, ...) _usbi_log(ctx, LOG_LEVEL_WARNING, __VA_ARGS__) -#define usbi_err(ctx, ...) _usbi_log(ctx, LOG_LEVEL_ERROR, __VA_ARGS__) +#define usbi_info(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_INFO, __VA_ARGS__) +#define usbi_warn(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_WARNING, __VA_ARGS__) +#define usbi_err(ctx, ...) _usbi_log(ctx, LIBUSB_LOG_LEVEL_ERROR, __VA_ARGS__) -#else /* !defined(_MSC_VER) || _MSC_VER > 1200 */ - -void usbi_log_v(struct libusb_context *ctx, enum usbi_log_level level, - const char *function, const char *format, va_list args); +#else /* !defined(_MSC_VER) || _MSC_VER >= 1400 */ #ifdef ENABLE_LOGGING #define LOG_BODY(ctxt, level) \ @@ -157,57 +200,50 @@ void usbi_log_v(struct libusb_context *ctx, enum usbi_log_level level, va_end(args); \ } #else -#define LOG_BODY(ctxt, level) { } +#define LOG_BODY(ctxt, level) do { (void)(ctxt); } while(0) #endif static inline void usbi_info(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx,LOG_LEVEL_INFO) + LOG_BODY(ctx,LIBUSB_LOG_LEVEL_INFO) static inline void usbi_warn(struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx,LOG_LEVEL_WARNING) + LOG_BODY(ctx,LIBUSB_LOG_LEVEL_WARNING) static inline void usbi_err( struct libusb_context *ctx, const char *format, ...) - LOG_BODY(ctx,LOG_LEVEL_ERROR) + LOG_BODY(ctx,LIBUSB_LOG_LEVEL_ERROR) static inline void usbi_dbg(const char *format, ...) -#ifdef ENABLE_DEBUG_LOGGING - LOG_BODY(NULL,LOG_LEVEL_DEBUG) -#else -{ } -#endif + LOG_BODY(NULL,LIBUSB_LOG_LEVEL_DEBUG) -#endif /* !defined(_MSC_VER) || _MSC_VER > 1200 */ +#endif /* !defined(_MSC_VER) || _MSC_VER >= 1400 */ #define USBI_GET_CONTEXT(ctx) if (!(ctx)) (ctx) = usbi_default_context #define DEVICE_CTX(dev) ((dev)->ctx) #define HANDLE_CTX(handle) (DEVICE_CTX((handle)->dev)) #define TRANSFER_CTX(transfer) (HANDLE_CTX((transfer)->dev_handle)) #define ITRANSFER_CTX(transfer) \ - (TRANSFER_CTX(__USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer))) + (TRANSFER_CTX(USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer))) -/* Internal abstractions for thread synchronization and poll */ -#if defined(THREADS_POSIX) -#include -#elif defined(OS_WINDOWS) -#include -#endif +#define IS_EPIN(ep) (0 != ((ep) & LIBUSB_ENDPOINT_IN)) +#define IS_EPOUT(ep) (!IS_EPIN(ep)) +#define IS_XFERIN(xfer) (0 != ((xfer)->endpoint & LIBUSB_ENDPOINT_IN)) +#define IS_XFEROUT(xfer) (!IS_XFERIN(xfer)) -#if defined(OS_LINUX) || defined(OS_DARWIN) -#include "poll_posix.h" -#elif defined(OS_WINDOWS) -#include -#endif +/* Internal abstraction for thread synchronization */ +#include "threads_posix.h" extern struct libusb_context *usbi_default_context; +/* Forward declaration for use in context (fully defined inside poll abstraction) */ +struct pollfd; + struct libusb_context { int debug; int debug_fixed; - /* internal control pipe, used for interrupting event handling when - * something needs to modify poll fds. */ - int ctrl_pipe[2]; + /* internal event pipe, used for signalling occurrence of an internal event. */ + int event_pipe[2]; struct list_head usb_devs; usbi_mutex_t usb_devs_lock; @@ -217,6 +253,10 @@ struct libusb_context { struct list_head open_devs; usbi_mutex_t open_devs_lock; + /* A list of registered hotplug callbacks */ + struct list_head hotplug_cbs; + usbi_mutex_t hotplug_cbs_lock; + /* this is a list of in-flight transfer handles, sorted by timeout * expiration. URBs to timeout the soonest are placed at the beginning of * the list, URBs that will time out later are placed after, and urbs with @@ -224,15 +264,6 @@ struct libusb_context { struct list_head flying_transfers; usbi_mutex_t flying_transfers_lock; - /* list of poll fds */ - struct list_head pollfds; - usbi_mutex_t pollfds_lock; - - /* a counter that is set when we want to interrupt event handling, in order - * to modify the poll fd set. and a lock to protect it. */ - unsigned int pollfd_modify; - usbi_mutex_t pollfd_modify_lock; - /* user callbacks for pollfd changes */ libusb_pollfd_added_cb fd_added_cb; libusb_pollfd_removed_cb fd_removed_cb; @@ -249,13 +280,42 @@ struct libusb_context { usbi_mutex_t event_waiters_lock; usbi_cond_t event_waiters_cond; + /* A lock to protect internal context event data. */ + usbi_mutex_t event_data_lock; + + /* A counter that is set when we want to interrupt and prevent event handling, + * in order to safely close a device. Protected by event_data_lock. */ + unsigned int device_close; + + /* list and count of poll fds and an array of poll fd structures that is + * (re)allocated as necessary prior to polling, and a flag to indicate + * when the list of poll fds has changed since the last poll. + * Protected by event_data_lock. */ + struct list_head ipollfds; + struct pollfd *pollfds; + POLL_NFDS_TYPE pollfds_cnt; + unsigned int pollfds_modified; + + /* A list of pending hotplug messages. Protected by event_data_lock. */ + struct list_head hotplug_msgs; + + /* A list of pending completed transfers. Protected by event_data_lock. */ + struct list_head completed_transfers; + #ifdef USBI_TIMERFD_AVAILABLE /* used for timeout handling, if supported by OS. * this timerfd is maintained to trigger on the next pending timeout */ int timerfd; #endif + + struct list_head list; }; +/* Update the following macro if new event sources are added */ +#define usbi_pending_events(ctx) \ + ((ctx)->device_close || (ctx)->pollfds_modified \ + || !list_empty(&(ctx)->hotplug_msgs) || !list_empty(&(ctx)->completed_transfers)) + #ifdef USBI_TIMERFD_AVAILABLE #define usbi_using_timerfd(ctx) ((ctx)->timerfd >= 0) #else @@ -271,12 +331,25 @@ struct libusb_device { struct libusb_context *ctx; uint8_t bus_number; + uint8_t port_number; + struct libusb_device* parent_dev; uint8_t device_address; uint8_t num_configurations; + enum libusb_speed speed; struct list_head list; unsigned long session_data; - unsigned char os_priv[0]; + + struct libusb_device_descriptor device_descriptor; + int attached; + + unsigned char os_priv +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + [] /* valid C99 code */ +#else + [0] /* non-standard, but usually working code */ +#endif + ; }; struct libusb_device_handle { @@ -286,11 +359,16 @@ struct libusb_device_handle { struct list_head list; struct libusb_device *dev; - unsigned char os_priv[0]; + int auto_detach_kernel_driver; + unsigned char os_priv +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + [] /* valid C99 code */ +#else + [0] /* non-standard, but usually working code */ +#endif + ; }; -#define USBI_TRANSFER_TIMED_OUT (1<<0) - enum { USBI_CLOCK_MONOTONIC, USBI_CLOCK_REALTIME @@ -312,8 +390,10 @@ enum { struct usbi_transfer { int num_iso_packets; struct list_head list; + struct list_head completed_list; struct timeval timeout; int transferred; + uint32_t stream_id; uint8_t flags; /* this lock is held during libusb_submit_transfer() and @@ -324,12 +404,42 @@ struct usbi_transfer { * its completion (presumably there would be races within your OS backend * if this were possible). */ usbi_mutex_t lock; + + /* this lock should be held whenever viewing or modifying flags + * relating to the transfer state */ + usbi_mutex_t flags_lock; }; -#define __USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ +enum usbi_transfer_flags { + /* The transfer has timed out */ + USBI_TRANSFER_TIMED_OUT = 1 << 0, + + /* Set by backend submit_transfer() if the OS handles timeout */ + USBI_TRANSFER_OS_HANDLES_TIMEOUT = 1 << 1, + + /* Cancellation was requested via libusb_cancel_transfer() */ + USBI_TRANSFER_CANCELLING = 1 << 2, + + /* Operation on the transfer failed because the device disappeared */ + USBI_TRANSFER_DEVICE_DISAPPEARED = 1 << 3, + + /* Transfer is currently being submitted */ + USBI_TRANSFER_SUBMITTING = 1 << 4, + + /* Transfer successfully submitted by backend */ + USBI_TRANSFER_IN_FLIGHT = 1 << 5, + + /* Completion handler has run */ + USBI_TRANSFER_COMPLETED = 1 << 6, + + /* The transfer timeout has been handled */ + USBI_TRANSFER_TIMEOUT_HANDLED = 1 << 7, +}; + +#define USBI_TRANSFER_TO_LIBUSB_TRANSFER(transfer) \ ((struct libusb_transfer *)(((unsigned char *)(transfer)) \ + sizeof(struct usbi_transfer))) -#define __LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer) \ +#define LIBUSB_TRANSFER_TO_USBI_TRANSFER(transfer) \ ((struct usbi_transfer *)(((unsigned char *)(transfer)) \ - sizeof(struct usbi_transfer))) @@ -364,13 +474,36 @@ void usbi_handle_disconnect(struct libusb_device_handle *handle); int usbi_handle_transfer_completion(struct usbi_transfer *itransfer, enum libusb_transfer_status status); int usbi_handle_transfer_cancellation(struct usbi_transfer *transfer); +void usbi_signal_transfer_completion(struct usbi_transfer *transfer); -int usbi_parse_descriptor(unsigned char *source, char *descriptor, void *dest, - int host_endian); +int usbi_parse_descriptor(const unsigned char *source, const char *descriptor, + void *dest, int host_endian); +int usbi_device_cache_descriptor(libusb_device *dev); int usbi_get_config_index_by_value(struct libusb_device *dev, uint8_t bConfigurationValue, int *idx); -/* polling */ +void usbi_connect_device (struct libusb_device *dev); +void usbi_disconnect_device (struct libusb_device *dev); + +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) */ +#include +#include "poll_posix.h" + +#if (defined(OS_WINDOWS) || defined(OS_WINCE)) && !defined(__GNUC__) +#define snprintf _snprintf +#define vsnprintf _vsnprintf +int usbi_gettimeofday(struct timeval *tp, void *tzp); +#define LIBUSB_GETTIMEOFDAY_WIN32 +#define HAVE_USBI_GETTIMEOFDAY +#else +#ifdef HAVE_GETTIMEOFDAY +#define usbi_gettimeofday(tv, tz) gettimeofday((tv), (tz)) +#define HAVE_USBI_GETTIMEOFDAY +#endif +#endif struct usbi_pollfd { /* must come first */ @@ -381,7 +514,6 @@ struct usbi_pollfd { int usbi_add_pollfd(struct libusb_context *ctx, int fd, short events); void usbi_remove_pollfd(struct libusb_context *ctx, int fd); -void usbi_fd_notification(struct libusb_context *ctx); /* device discovery */ @@ -393,7 +525,13 @@ void usbi_fd_notification(struct libusb_context *ctx); struct discovered_devs { size_t len; size_t capacity; - struct libusb_device *devices[0]; + struct libusb_device *devices +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + [] /* valid C99 code */ +#else + [0] /* non-standard, but usually working code */ +#endif + ; }; struct discovered_devs *discovered_devs_append( @@ -407,6 +545,9 @@ struct usbi_os_backend { /* A human-readable name for your backend, e.g. "Linux usbfs" */ const char *name; + /* Binary mask for backend specific capabilities */ + uint32_t caps; + /* Perform initialization of your backend. You might use this function * to determine specific capabilities of the system, allocate required * data structures for later, etc. @@ -442,8 +583,8 @@ struct usbi_os_backend { * * After computing a session ID for a device, call * usbi_get_device_by_session_id(). This function checks if libusb already - * knows about the device, and if so, it provides you with a libusb_device - * structure for it. + * knows about the device, and if so, it provides you with a reference + * to a libusb_device structure for it. * * If usbi_get_device_by_session_id() returns NULL, it is time to allocate * a new device structure for the device. Call usbi_alloc_device() to @@ -472,11 +613,30 @@ struct usbi_os_backend { * This function is executed when the user wishes to retrieve a list * of USB devices connected to the system. * + * If the backend has hotplug support, this function is not used! + * * Return 0 on success, or a LIBUSB_ERROR code on failure. */ int (*get_device_list)(struct libusb_context *ctx, struct discovered_devs **discdevs); + /* Apps which were written before hotplug support, may listen for + * hotplug events on their own and call libusb_get_device_list on + * device addition. In this case libusb_get_device_list will likely + * return a list without the new device in there, as the hotplug + * event thread will still be busy enumerating the device, which may + * take a while, or may not even have seen the event yet. + * + * To avoid this libusb_get_device_list will call this optional + * function for backends with hotplug support before copying + * ctx->usb_devs to the user. In this function the backend should + * ensure any pending hotplug events are fully processed before + * returning. + * + * Optional, should be implemented by backends with hotplug support. + */ + void (*hotplug_poll)(void); + /* Open a device for I/O and other USB operations. The device handle * is preallocated for you, you can retrieve the device in question * through handle->dev. @@ -580,12 +740,28 @@ struct usbi_os_backend { * (LE). If it returns the multi-byte values in host-endian format, * set the host_endian output parameter to "1". * - * Return 0 on success or a LIBUSB_ERROR code on failure. + * Return the length read on success or a LIBUSB_ERROR code on failure. */ int (*get_config_descriptor)(struct libusb_device *device, uint8_t config_index, unsigned char *buffer, size_t len, int *host_endian); + /* Like get_config_descriptor but then by bConfigurationValue instead + * of by index. + * + * Optional, if not present the core will call get_config_descriptor + * for all configs until it finds the desired bConfigurationValue. + * + * Returns a pointer to the raw-descriptor in *buffer, this memory + * is valid as long as device is valid. + * + * Returns the length of the returned raw-descriptor on success, + * or a LIBUSB_ERROR code on failure. + */ + int (*get_config_descriptor_by_value)(struct libusb_device *device, + uint8_t bConfigurationValue, unsigned char **buffer, + int *host_endian); + /* Get the bConfigurationValue for the active configuration for a device. * Optional. This should only be implemented if you can retrieve it from * cache (don't generate I/O). @@ -628,7 +804,7 @@ struct usbi_os_backend { * This function should not generate any bus I/O and should not block. * Interface claiming is a logical operation that simply ensures that * no other drivers/applications are using the interface, and after - * claiming, no other drivers/applicatiosn can use the interface because + * claiming, no other drivers/applications can use the interface because * we now "own" it. * * Return: @@ -707,6 +883,14 @@ struct usbi_os_backend { */ int (*reset_device)(struct libusb_device_handle *handle); + /* Alloc num_streams usb3 bulk streams on the passed in endpoints */ + int (*alloc_streams)(struct libusb_device_handle *handle, + uint32_t num_streams, unsigned char *endpoints, int num_endpoints); + + /* Free usb3 bulk streams allocated with alloc_streams */ + int (*free_streams)(struct libusb_device_handle *handle, + unsigned char *endpoints, int num_endpoints); + /* Determine if a kernel driver is active on an interface. Optional. * * The presence of a kernel driver on an interface indicates that any @@ -769,6 +953,8 @@ struct usbi_os_backend { * * This function must not block. * + * This function gets called with the flying_transfers_lock locked! + * * Return: * - 0 on success * - LIBUSB_ERROR_NO_DEVICE if the device has been disconnected @@ -796,8 +982,14 @@ struct usbi_os_backend { */ void (*clear_transfer_priv)(struct usbi_transfer *itransfer); - /* Handle any pending events. This involves monitoring any active - * transfers and processing their completion or cancellation. + /* Handle any pending events on file descriptors. Optional. + * + * Provide this function when file descriptors directly indicate device + * or transfer activity. If your backend does not have such file descriptors, + * implement the handle_transfer_completion function below. + * + * This involves monitoring any active transfers and processing their + * completion or cancellation. * * The function is passed an array of pollfd structures (size nfds) * as a result of the poll() system call. The num_ready parameter @@ -823,7 +1015,32 @@ struct usbi_os_backend { * Return 0 on success, or a LIBUSB_ERROR code on failure. */ int (*handle_events)(struct libusb_context *ctx, - struct pollfd *fds, nfds_t nfds, int num_ready); + struct pollfd *fds, POLL_NFDS_TYPE nfds, int num_ready); + + /* Handle transfer completion. Optional. + * + * Provide this function when there are no file descriptors available + * that directly indicate device or transfer activity. If your backend does + * have such file descriptors, implement the handle_events function above. + * + * Your backend must tell the library when a transfer has completed by + * calling usbi_signal_transfer_completion(). You should store any private + * information about the transfer and its completion status in the transfer's + * private backend data. + * + * During event handling, this function will be called on each transfer for + * which usbi_signal_transfer_completion() was called. + * + * For any cancelled transfers, call usbi_handle_transfer_cancellation(). + * For completed transfers, call usbi_handle_transfer_completion(). + * For control/bulk/interrupt transfers, populate the "transferred" + * element of the appropriate usbi_transfer structure before calling the + * above functions. For isochronous transfers, populate the status and + * transferred fields of the iso packet descriptors of the transfer. + * + * Return 0 on success, or a LIBUSB_ERROR code on failure. + */ + int (*handle_transfer_completion)(struct usbi_transfer *itransfer); /* Get time from specified clock. At least two clocks must be implemented by the backend: USBI_CLOCK_REALTIME, and USBI_CLOCK_MONOTONIC. @@ -855,19 +1072,23 @@ struct usbi_os_backend { * usbi_transfer_get_os_priv() on the appropriate usbi_transfer instance. */ size_t transfer_priv_size; - - /* Mumber of additional bytes for os_priv for each iso packet. - * Can your backend use this? */ - /* FIXME: linux can't use this any more. if other OS's cannot either, - * then remove this */ - size_t add_iso_packet_size; }; extern const struct usbi_os_backend * const usbi_backend; extern const struct usbi_os_backend linux_usbfs_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; 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/include/poll_posix.h b/include/poll_posix.h index 17298a5..5b4b2c9 100644 --- a/include/poll_posix.h +++ b/include/poll_posix.h @@ -1,12 +1,11 @@ -#ifndef __LIBUSB_POLL_POSIX_H__ -#define __LIBUSB_POLL_POSIX_H__ +#ifndef LIBUSB_POLL_POSIX_H +#define LIBUSB_POLL_POSIX_H -#include -#include #define usbi_write write #define usbi_read read #define usbi_close close -#define usbi_pipe pipe #define usbi_poll poll -#endif /* __LIBUSB_POLL_POSIX_H__ */ +int usbi_pipe(int pipefd[2]); + +#endif /* LIBUSB_POLL_POSIX_H */ diff --git a/include/threads_posix.h b/include/threads_posix.h index dc558d4..d7a5d21 100644 --- a/include/threads_posix.h +++ b/include/threads_posix.h @@ -1,7 +1,7 @@ /* * libusb synchronization using POSIX Threads * - * Copyright (C) 2010 Peter Stuge + * Copyright © 2010 Peter Stuge * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,8 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef __LIBUSB_THREADS_POSIX_H__ -#define __LIBUSB_THREADS_POSIX_H__ +#ifndef LIBUSB_THREADS_POSIX_H +#define LIBUSB_THREADS_POSIX_H #include @@ -41,6 +41,10 @@ #define usbi_cond_timedwait pthread_cond_timedwait #define usbi_cond_broadcast pthread_cond_broadcast #define usbi_cond_destroy pthread_cond_destroy -#define usbi_cond_signal pthread_cond_signal +#define usbi_cond_signal pthread_cond_signal -#endif /* __LIBUSB_THREADS_POSIX_H__ */ +extern int usbi_mutex_init_recursive(pthread_mutex_t *mutex, pthread_mutexattr_t *attr); + +int usbi_get_tid(void); + +#endif /* LIBUSB_THREADS_POSIX_H */ diff --git a/include/version.h b/include/version.h new file mode 100644 index 0000000..0e3a363 --- /dev/null +++ b/include/version.h @@ -0,0 +1,18 @@ +/* This file is parsed by m4 and windres and RC.EXE so please keep it simple. */ +#include "version_nano.h" +#ifndef LIBUSB_MAJOR +#define LIBUSB_MAJOR 1 +#endif +#ifndef LIBUSB_MINOR +#define LIBUSB_MINOR 0 +#endif +#ifndef LIBUSB_MICRO +#define LIBUSB_MICRO 20 +#endif +#ifndef LIBUSB_NANO +#define LIBUSB_NANO 0 +#endif +/* LIBUSB_RC is the release candidate suffix. Should normally be empty. */ +#ifndef LIBUSB_RC +#define LIBUSB_RC "" +#endif diff --git a/include/version_nano.h b/include/version_nano.h new file mode 100644 index 0000000..4afcd97 --- /dev/null +++ b/include/version_nano.h @@ -0,0 +1 @@ +#define LIBUSB_NANO 11004 diff --git a/payload.S b/payload.S index 71d7ab1..07b8b57 100644 --- a/payload.S +++ b/payload.S @@ -4,9 +4,11 @@ @constants ----------------------------------- .pool @ usb_wait_for_image call offset -.set RET_ADDR, 0x7ef @ A4 +@ these are defined in device_def.S (created by make) +@.set RET_ADDR, 0x7ef @ A4 @.set RET_ADDR, 0x8b7 @ iPod 3G @.set RET_ADDR, 0x8b7 @ iPhone 3Gs new bootrom +.include "device_def.S" .set loadaddr, 0x84000000 .set maxsize, 0x24000