the Fink project is an effort to port
popular Unix programs to Mac OS X
Package: libusb
Version: 0.1.12
Revision: 1015
Maintainer: Ben Hines
Source: http://download.sourceforge.net/%n/%n-%v.tar.gz
Source-MD5: caf182cbc7565dac0fd72155919672e6
BuildDepends: fink (>= 0.24.12-1)
BuildDependsOnly: true
Depends: %N-shlibs (= %v-%r)
GCC: 4.0
SetLDFLAGS: -Wl,-framework,CoreFoundation -Wl,-framework,IOKit
NoSetMAKEFLAGS: true
SetMAKEFLAGS: -j1
CompileScript: <<
#!/bin/sh -ev
# cp %p/share/libtool/ltmain.sh .
# perl -pi.bak -e 's/shrext_cmds/shrext/' ltmain.sh
# perl -pi.bak -e 's,-flat_namespace -undefined suppress,-undefined dynamic_lookup,g' configure
perl -pi.bak -e 's|(\-framework) \-Wl(,\S+)|$1$2|g' configure
./configure --disable-build-docs %c
# /usr/bin/perl -pi.bak -e 's/^library_names_spec=.*/library_names_spec=\"\\\${libname}\\\${release}\\\${versuffix}.dylib \\\${libname}\${release}\\\${major}\dylib \\\${libname}.dylib\"/g' libtool
/usr/bin/head -n 7 usb.c >> LICENSE
make
<<
PatchFile: %n.patch
PatchFile-MD5: 834282b7beb069f89c2ec300cf5469e4
InstallScript: <<
make install DESTDIR=%d
# for some reason, libusb's build strips out the -Wl's?
# perl -pi -e 's/-Xlinker -framework -Xlinker (\S*)/-Wl,-framework,$1/g; s/-framework (\S*)/-Wl,-framework,$1/g;' %i/bin/libusb-config
<<
DocFiles: AUTHORS INSTALL.libusb NEWS README LICENSE
SplitOff: <<
Package: %N-shlibs
Files: lib/libusb-*.dylib lib/libusbpp-*.dylib
Shlibs: <<
%p/lib/libusb-0.1.4.dylib 9.0.0 %n (>= 0.1.8-10)
%p/lib/libusbpp-0.1.4.dylib 9.0.0 %n (>= 0.1.8-10)
<<
DocFiles: LICENSE
<<
#
Description: Portable library for USB device access
DescDetail: <<
libusb's aim is to create a library for use by user level applications
to access USB devices regardless of OS.
<<
License: LGPL
Homepage: http://libusb.sourceforge.net/
diff --git a/darwin.c b/darwin.c
--- a/darwin.c
+++ b/darwin.c
@@ -1,8 +1,10 @@
/*
* Darwin/MacOS X Support
*
- * (c) 2002-2005 Nathan Hjelm
+ * (c) 2002-2006 Nathan Hjelm
*
+ * (06/26/2006):
+ * - Bulk functions no longer use async transfer functions.
* (04/17/2005):
* - Lots of minor fixes.
* - Endpoint table now made by claim_interface to fix a bug.
@@ -51,6 +53,7 @@
#include "config.h"
#endif
+#include
#include
#include
#include
@@ -146,7 +149,6 @@
#define IO_OBJECT_NULL ((io_object_t)0)
#endif
-/* Darwin/OS X impl does not use fd field, instead it uses this */
struct darwin_dev_handle {
usb_device_t **device;
usb_interface_t **interface;
@@ -157,7 +159,6 @@
unsigned char *endpoint_addrs;
};
-static CFMutableDictionaryRef matchingDict;
static IONotificationPortRef gNotifyPort;
static mach_port_t masterPort = MACH_PORT_NULL;
@@ -223,6 +224,7 @@
static int usb_setup_iterator (io_iterator_t *deviceIterator)
{
int result;
+ CFMutableDictionaryRef matchingDict;
/* set up the matching dictionary for class IOUSBDevice and its subclasses.
It will be consumed by the IOServiceGetMatchingServices call */
@@ -247,7 +249,8 @@
io_cf_plugin_ref_t *plugInInterface = NULL;
usb_device_t **device;
io_service_t usbDevice;
- long result, score;
+ long result;
+ SInt32 score;
if (!IOIteratorIsValid (deviceIterator) || !(usbDevice = IOIteratorNext(deviceIterator)))
return NULL;
@@ -447,7 +450,7 @@
IOUSBFindInterfaceRequest request;
struct darwin_dev_handle *device;
- long score;
+ SInt32 score;
int current_interface;
device = dev->impl_info;
@@ -756,6 +759,70 @@
return -1;
}
+static int usb_bulk_transfer (usb_dev_handle *dev, int ep, char *bytes, u_int32_t size, int timeout, int usb_bt_read)
+{
+ struct darwin_dev_handle *device;
+
+ io_return_t result = -1;
+
+ int pipeRef;
+
+ u_int8_t transferType, direction, number, interval;
+ u_int16_t maxPacketSize;
+
+ if (!dev)
+ USB_ERROR_STR ( -ENXIO, "libusb/darwin.c usb_bulk_transfer: Called with NULL device" );
+
+ if ((device = dev->impl_info) == NULL)
+ USB_ERROR_STR ( -ENOENT, "libusb/darwin.c usb_bulk_transfer: Device not open" );
+
+ /* interface is not open */
+ if (!device->interface)
+ USB_ERROR_STR(-EACCES, "libusb/darwin.c usb_bulk_transfer: Interface used before it was opened");
+
+
+ /* Set up transfer */
+ if ((pipeRef = ep_to_pipeRef(device, ep)) < 0)
+ USB_ERROR_STR ( -EINVAL, "libusb/darwin.c usb_bulk_transfer: Invalid pipe reference" );
+
+ (*(device->interface))->GetPipeProperties (device->interface, pipeRef, &direction, &number,
+ &transferType, &maxPacketSize, &interval);
+ /* Transfer set up complete */
+
+ if (usb_debug > 0)
+ fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: Transfering %i bytes of data on endpoint 0x%02x\n", size, ep);
+
+ /* Do bulk transfer */
+ if (transferType == kUSBInterrupt && usb_debug > 3)
+ fprintf (stderr, "libusb/darwin.c usb_bulk_transfer: USB pipe is an interrupt pipe. Timeouts will not be used.\n");
+
+#if !defined(LIBUSB_NO_TIMEOUT_INTERFACE)
+ if ( transferType != kUSBInterrupt) {
+ if (usb_bt_read != 0)
+ result = (*(device->interface))->ReadPipeTO (device->interface, pipeRef, bytes, (UInt32 *)&size, timeout, timeout);
+ else
+ result = (*(device->interface))->WritePipeTO (device->interface, pipeRef, bytes, size, timeout, timeout);
+
+ /* pipe bits may need to be cleared after a timeout. should this be done here or in user code? */
+ if (result == kIOUSBTransactionTimeout && (*(device->interface))->GetPipeStatus (device->interface, pipeRef) == kIOUSBPipeStalled)
+ usb_clear_halt (dev, ep);
+ } else
+#endif
+ {
+ if (usb_bt_read != 0)
+ result = (*(device->interface))->ReadPipe (device->interface, pipeRef, bytes, (UInt32 *)&size);
+ else
+ result = (*(device->interface))->WritePipe (device->interface, pipeRef, bytes, size);
+ }
+
+ if (result != kIOReturnSuccess)
+ USB_ERROR_STR (-darwin_to_errno (result), "libusb/darwin.c usb_bulk_transfer: %s", darwin_error_str (result));
+
+ return size;
+}
+
+#if 0
+/* NOT USED */
/* argument to handle multiple parameters to rw_completed */
struct rw_complete_arg {
UInt32 io_size;
@@ -777,7 +844,7 @@
CFRunLoopStop(rw_arg->cf_loop);
}
-static int usb_bulk_transfer (usb_dev_handle *dev, int ep, char *bytes, int size, int timeout,
+static int usb_bulk_transfer_async (usb_dev_handle *dev, int ep, char *bytes, int size, int timeout,
rw_async_func_t rw_async, rw_async_to_func_t rw_async_to)
{
struct darwin_dev_handle *device;
@@ -813,11 +880,12 @@
(*(device->interface))->GetPipeProperties (device->interface, pipeRef, &direction, &number,
&transferType, &maxPacketSize, &interval);
- (*(device->interface))->CreateInterfaceAsyncEventSource(device->interface, &cfSource);
- CFRunLoopAddSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
-
bzero((void *)&rw_arg, sizeof(struct rw_complete_arg));
rw_arg.cf_loop = CFRunLoopGetCurrent();
+ CFRetain (rw_arg.cf_loop);
+
+ (*(device->interface))->CreateInterfaceAsyncEventSource(device->interface, &cfSource);
+ CFRunLoopAddSource(rw_arg.cf_loop, cfSource, kCFRunLoopDefaultMode);
/* Transfer set up complete */
if (usb_debug > 0)
@@ -842,11 +910,12 @@
(*(device->interface))->AbortPipe(device->interface, pipeRef);
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true); /* Pick up aborted callback */
if (usb_debug)
- fprintf(stderr, "usb_bulk_read: input timed out\n");
+ fprintf(stderr, "usb_bulk_transfer: timed out\n");
}
}
- CFRunLoopRemoveSource(CFRunLoopGetCurrent(), cfSource, kCFRunLoopDefaultMode);
+ CFRunLoopRemoveSource(rw_arg.cf_loop, cfSource, kCFRunLoopDefaultMode);
+ CFRelease (rw_arg.cf_loop);
/* Check the return code of both the write and completion functions. */
if (result != kIOReturnSuccess || (rw_arg.result != kIOReturnSuccess &&
@@ -870,24 +939,16 @@
return rw_arg.io_size;
}
+#endif
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
{
int result;
- rw_async_to_func_t to_func = NULL;
- struct darwin_dev_handle *device;
if (dev == NULL || dev->impl_info == NULL)
return -EINVAL;
- device = dev->impl_info;
-
-#if !defined (LIBUSB_NO_TIMEOUT_INTERFACE)
- to_func = (*(device->interface))->WritePipeAsyncTO;
-#endif
-
- if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout,
- (*(device->interface))->WritePipeAsync, to_func)) < 0)
+ if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout, 0)) < 0)
USB_ERROR_STR (result, "usb_bulk_write: An error occured during write (see messages above)");
return result;
@@ -896,28 +957,19 @@
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout)
{
int result;
- rw_async_to_func_t to_func = NULL;
- struct darwin_dev_handle *device;
if (dev == NULL || dev->impl_info == NULL)
return -EINVAL;
ep |= 0x80;
-
- device = dev->impl_info;
-#if !defined (LIBUSB_NO_TIMEOUT_INTERFACE)
- to_func = (*(device->interface))->ReadPipeAsyncTO;
-#endif
-
- if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout,
- (*(device->interface))->ReadPipeAsync, to_func)) < 0)
+ if ((result = usb_bulk_transfer (dev, ep, bytes, size, timeout, 1)) < 0)
USB_ERROR_STR (result, "usb_bulk_read: An error occured during read (see messages above)");
return result;
}
-/* interrupt endpoints seem to be treated just like any other endpoint under OSX/Darwin */
+/* interrupt endpoints appear to be treated the same as non-interrupt endpoints under OSX/Darwin */
int usb_interrupt_write(usb_dev_handle *dev, int ep, char *bytes, int size,
int timeout)
{
@@ -1064,7 +1116,8 @@
result = (*(device))->GetDeviceAddress(device, (USBDeviceAddress *)&address);
if (usb_debug >= 2)
- fprintf(stderr, "usb_os_find_devices: Found USB device at location 0x%08lx\n", location);
+ fprintf(stderr, "usb_os_find_devices: Found USB device at location 0x%08" PRIx32 "\n",
+ (uint32_t) location);
/* first byte of location appears to be associated with the device's bus */
if (location >> 24 == bus_loc >> 24) {
@@ -1091,8 +1144,8 @@
LIST_ADD(fdev, dev);
if (usb_debug >= 2)
- fprintf(stderr, "usb_os_find_devices: Found %s on %s at location 0x%08lx\n",
- dev->filename, bus->dirname, location);
+ fprintf(stderr, "usb_os_find_devices: Found %s on %s at location 0x%08" PRIx32 "\n",
+ dev->filename, bus->dirname, (uint32_t) location);
}
/* release the device now */
@@ -1177,7 +1230,12 @@
if ((pipeRef = ep_to_pipeRef(device, ep)) == -1)
USB_ERROR(-EINVAL);
+#if (InterfaceVersion < 190)
result = (*(device->interface))->ClearPipeStall(device->interface, pipeRef);
+#else
+ /* newer versions of darwin support clearing additional bits on the device's endpoint */
+ result = (*(device->interface))->ClearPipeStallBothEnds(device->interface, pipeRef);
+#endif
if (result != kIOReturnSuccess)
USB_ERROR_STR(-darwin_to_errno(result), "usb_clear_halt(ClearPipeStall): %s", darwin_error_str(result));