diff options
Diffstat (limited to 'libusb/os')
-rw-r--r-- | libusb/os/darwin_usb.c | 211 | ||||
-rw-r--r-- | libusb/os/linux_usbfs.c | 30 | ||||
-rw-r--r-- | libusb/os/sources | 10 | ||||
-rw-r--r-- | libusb/os/threads_posix.h | 46 | ||||
-rw-r--r-- | libusb/os/threads_windows.c | 207 | ||||
-rw-r--r-- | libusb/os/threads_windows.h | 83 | ||||
-rw-r--r-- | libusb/os/windows_compat.c | 4 | ||||
-rw-r--r-- | libusb/os/windows_compat.h | 3 | ||||
-rw-r--r-- | libusb/os/windows_usb.c | 8 |
9 files changed, 472 insertions, 130 deletions
diff --git a/libusb/os/darwin_usb.c b/libusb/os/darwin_usb.c index de3e9a6..1fc6a0e 100644 --- a/libusb/os/darwin_usb.c +++ b/libusb/os/darwin_usb.c @@ -1,6 +1,6 @@ /* * darwin backend for libusb 1.0 - * Copyright (C) 2008-2009 Nathan Hjelm <hjelmn@users.sourceforge.net> + * Copyright (C) 2008-2010 Nathan Hjelm <hjelmn@users.sourceforge.net> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -44,6 +44,7 @@ static mach_port_t libusb_darwin_mp = 0; /* master port */ static CFRunLoopRef libusb_darwin_acfl = NULL; /* async cf loop */ +static int initCount = 0; /* async event thread */ static pthread_t libusb_darwin_at; @@ -83,6 +84,8 @@ static const char *darwin_error_str (int result) { return "device not responding"; case kIOReturnOverrun: return "data overrun"; + case kIOReturnCannotWire: + return "physical memory can not be wired down"; default: return "unknown error"; } @@ -121,7 +124,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui int8_t i, iface; - _usbi_log (HANDLE_CTX(dev_handle), LOG_LEVEL_INFO, "converting ep address 0x%02x to pipeRef and interface", ep); + usbi_info (HANDLE_CTX(dev_handle), "converting ep address 0x%02x to pipeRef and interface", ep); for (iface = 0 ; iface < USB_MAXINTERFACES ; iface++) { cInterface = &priv->interfaces[iface]; @@ -131,7 +134,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui if (cInterface->endpoint_addrs[i] == ep) { *pipep = i + 1; *ifcp = iface; - _usbi_log (HANDLE_CTX(dev_handle), LOG_LEVEL_INFO, "pipe %d on interface %d matches", *pipep, *ifcp); + usbi_info (HANDLE_CTX(dev_handle), "pipe %d on interface %d matches", *pipep, *ifcp); return 0; } } @@ -139,7 +142,7 @@ static int ep_to_pipeRef(struct libusb_device_handle *dev_handle, uint8_t ep, ui } /* No pipe found with the correct endpoint address */ - _usbi_log (HANDLE_CTX(dev_handle), LOG_LEVEL_WARNING, "no pipeRef found with endpoint address 0x%02x.", ep); + usbi_warn (HANDLE_CTX(dev_handle), "no pipeRef found with endpoint address 0x%02x.", ep); return -1; } @@ -218,7 +221,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { CFTypeRef locationCF; UInt32 message; - _usbi_log (ctx, LOG_LEVEL_INFO, "a device has been detached"); + usbi_info (ctx, "a device has been detached"); while ((device = IOIteratorNext (rem_devices)) != 0) { /* get the location from the i/o registry */ @@ -228,7 +231,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { CFRelease (locationCF); IOObjectRelease (device); - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); list_for_each_entry(handle, &ctx->open_devs, list, struct libusb_device_handle) { dpriv = (struct darwin_device_priv *)handle->dev->os_priv; @@ -241,7 +244,7 @@ static void darwin_devices_detached (void *ptr, io_iterator_t rem_devices) { } } - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); } } @@ -261,7 +264,7 @@ static void *event_thread_main (void *arg0) { io_notification_port_t libusb_notification_port; io_iterator_t libusb_rem_device_iterator; - _usbi_log (ctx, LOG_LEVEL_INFO, "creating hotplug event source"); + usbi_info (ctx, "creating hotplug event source"); CFRetain (CFRunLoopGetCurrent ()); @@ -277,7 +280,7 @@ static void *event_thread_main (void *arg0) { (void *)ctx, &libusb_rem_device_iterator); if (kresult != kIOReturnSuccess) { - _usbi_log (ctx, LOG_LEVEL_ERROR, "could not add hotplug event source: %s", darwin_error_str (kresult)); + usbi_err (ctx, "could not add hotplug event source: %s", darwin_error_str (kresult)); pthread_exit ((void *)kresult); } @@ -288,12 +291,12 @@ static void *event_thread_main (void *arg0) { /* let the main thread know about the async runloop */ libusb_darwin_acfl = CFRunLoopGetCurrent (); - _usbi_log (ctx, LOG_LEVEL_INFO, "libopenusb/darwin.c event_thread_main: thread ready to receive events"); + usbi_info (ctx, "libopenusb/darwin.c event_thread_main: thread ready to receive events"); /* run the runloop */ CFRunLoopRun(); - _usbi_log (ctx, LOG_LEVEL_INFO, "libopenusb/darwin.c event_thread_main: thread exiting"); + usbi_info (ctx, "libopenusb/darwin.c event_thread_main: thread exiting"); /* delete notification port */ CFRunLoopSourceInvalidate (libusb_notification_cfsource); @@ -309,33 +312,37 @@ static void *event_thread_main (void *arg0) { static int darwin_init(struct libusb_context *ctx) { IOReturn kresult; - /* Create the master port for talking to IOKit */ - if (!libusb_darwin_mp) { - kresult = IOMasterPort (MACH_PORT_NULL, &libusb_darwin_mp); + if (!(initCount++)) { + /* Create the master port for talking to IOKit */ + if (!libusb_darwin_mp) { + kresult = IOMasterPort (MACH_PORT_NULL, &libusb_darwin_mp); - if (kresult != kIOReturnSuccess || !libusb_darwin_mp) - return darwin_to_libusb (kresult); - } + if (kresult != kIOReturnSuccess || !libusb_darwin_mp) + return darwin_to_libusb (kresult); + } - pthread_create (&libusb_darwin_at, NULL, event_thread_main, (void *)ctx); + pthread_create (&libusb_darwin_at, NULL, event_thread_main, (void *)ctx); - while (!libusb_darwin_acfl) - usleep (10); + while (!libusb_darwin_acfl) + usleep (10); + } return 0; } static void darwin_exit (void) { - void *ret; + if (!(--initCount)) { + void *ret; - /* stop the async runloop */ - CFRunLoopStop (libusb_darwin_acfl); - pthread_join (libusb_darwin_at, &ret); + /* stop the async runloop */ + CFRunLoopStop (libusb_darwin_acfl); + pthread_join (libusb_darwin_at, &ret); - if (libusb_darwin_mp) - mach_port_deallocate(mach_task_self(), libusb_darwin_mp); + if (libusb_darwin_mp) + mach_port_deallocate(mach_task_self(), libusb_darwin_mp); - libusb_darwin_mp = 0; + libusb_darwin_mp = 0; + } } static int darwin_get_device_descriptor(struct libusb_device *dev, unsigned char *buffer, int *host_endian) { @@ -400,7 +407,7 @@ static int darwin_get_config_descriptor(struct libusb_device *dev, uint8_t confi if (!priv->device) { kresult = darwin_get_device (priv->location, &device); if (kresult || !device) { - _usbi_log (DEVICE_CTX (dev), LOG_LEVEL_ERROR, "could not find device: %s", darwin_error_str (kresult)); + usbi_err (DEVICE_CTX (dev), "could not find device: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -434,12 +441,13 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device UInt16 address, idVendor, idProduct; UInt8 bDeviceClass, bDeviceSubClass; IOUSBDevRequest req; - int ret; + int ret, need_unref = 0; dev = usbi_get_device_by_session_id(ctx, locationID); if (!dev) { - _usbi_log (ctx, LOG_LEVEL_INFO, "allocating new device for location 0x%08x", locationID); + usbi_info (ctx, "allocating new device for location 0x%08x", locationID); dev = usbi_alloc_device(ctx, locationID); + need_unref = 1; if (!dev) return LIBUSB_ERROR_NO_MEM; @@ -490,8 +498,9 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device (*device)->USBDeviceClose (device); if (ret != kIOReturnSuccess) { - _usbi_log (ctx, LOG_LEVEL_WARNING, "could not retrieve device descriptor: %s. skipping device", darwin_error_str (ret)); - libusb_unref_device(dev); + usbi_warn (ctx, "could not retrieve device descriptor: %s. skipping device", darwin_error_str (ret)); + if (need_unref) + libusb_unref_device(dev); return -1; } /**** end: retrieve device descriptors ****/ @@ -499,7 +508,7 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device /* catch buggy hubs (which appear to be virtual). Apple's own USB prober has problems with these devices. */ if (libusb_le16_to_cpu (priv->dev_descriptor.idProduct) != idProduct) { /* not a valid device */ - _usbi_log (ctx, LOG_LEVEL_WARNING, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device", + usbi_warn (ctx, "idProduct from iokit (%04x) does not match idProduct in descriptor (%04x). skipping device", idProduct, libusb_le16_to_cpu (priv->dev_descriptor.idProduct)); libusb_unref_device(dev); return -1; @@ -515,13 +524,14 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device ret = usbi_sanitize_device(dev); if (ret < 0) { - libusb_unref_device(dev); + if (need_unref) + libusb_unref_device(dev); return -1; } } else { priv = (struct darwin_device_priv *)dev->os_priv; - _usbi_log (ctx, LOG_LEVEL_INFO, "using existing device for location 0x%08x", locationID); + usbi_info (ctx, "using existing device for location 0x%08x", locationID); } /* append the device to the list of discovered devices */ @@ -531,8 +541,11 @@ static int process_new_device (struct libusb_context *ctx, usb_device_t **device *_discdevs = discdevs; - _usbi_log (ctx, LOG_LEVEL_INFO, "found device with address %d at %s", dev->device_address, priv->sys_path); + usbi_info (ctx, "found device with address %d at %s", dev->device_address, priv->sys_path); + if (need_unref) + libusb_unref_device(dev); + return 0; } @@ -569,7 +582,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { if (0 == dpriv->open_count) { kresult = darwin_get_device (dpriv->location, &darwin_device); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not find device: %s", darwin_error_str (kresult)); + usbi_err (HANDLE_CTX (dev_handle), "could not find device: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -579,7 +592,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { kresult = (*(dpriv->device))->USBDeviceOpenSeize (dpriv->device); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBDeviceOpen: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBDeviceOpen: %s", darwin_error_str(kresult)); switch (kresult) { case kIOReturnExclusiveAccess: @@ -616,7 +629,7 @@ static int darwin_open (struct libusb_device_handle *dev_handle) { usbi_add_pollfd(HANDLE_CTX(dev_handle), priv->fds[0], POLLIN); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "device open for access"); + usbi_info (HANDLE_CTX (dev_handle), "device open for access"); return 0; } @@ -629,7 +642,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { if (dpriv->open_count == 0) { /* something is probably very wrong if this is the case */ - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "Close called on a device that was not open!\n"); + usbi_err (HANDLE_CTX (dev_handle), "Close called on a device that was not open!\n"); return; } @@ -653,7 +666,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { if (kresult) { /* Log the fact that we had a problem closing the file, however failing a * close isn't really an error, so return success anyway */ - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBDeviceClose: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBDeviceClose: %s", darwin_error_str(kresult)); } } @@ -661,7 +674,7 @@ static void darwin_close (struct libusb_device_handle *dev_handle) { if (kresult) { /* Log the fact that we had a problem closing the file, however failing a * close isn't really an error, so return success anyway */ - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "Release: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult)); } dpriv->device = NULL; @@ -752,12 +765,12 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { u_int16_t dont_care2; int i; - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "building table of endpoints."); + usbi_info (HANDLE_CTX (dev_handle), "building table of endpoints."); /* retrieve the total number of endpoints on this interface */ kresult = (*(cInterface->interface))->GetNumEndpoints(cInterface->interface, &numep); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "can't get number of endpoints for interface: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "can't get number of endpoints for interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -767,12 +780,12 @@ static int get_endpoints (struct libusb_device_handle *dev_handle, int iface) { &dont_care2, &dont_care3); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "error getting pipe information for pipe %d: %s", i, darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "error getting pipe information for pipe %d: %s", i, darwin_error_str(kresult)); return darwin_to_libusb (kresult); } - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "interface: %i pipe %i: dir: %i number: %i", iface, i, direction, number); + usbi_info (HANDLE_CTX (dev_handle), "interface: %i pipe %i: dir: %i number: %i", iface, i, direction, number); cInterface->endpoint_addrs[i - 1] = ((direction << 7 & LIBUSB_ENDPOINT_DIR_MASK) | (number & LIBUSB_ENDPOINT_ADDRESS_MASK)); } @@ -806,50 +819,50 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i be configured. Otherwise, we need to do it ourselves, or there will be no interfaces for the device. */ - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "no interface found; selecting configuration" ); + usbi_info (HANDLE_CTX (dev_handle), "no interface found; selecting configuration" ); kresult = (*(dpriv->device))->GetNumberOfConfigurations (dpriv->device, &nConfig); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "GetNumberOfConfigurations: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "GetNumberOfConfigurations: %s", darwin_error_str(kresult)); return darwin_to_libusb(kresult); } if (nConfig < 1) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "GetNumberOfConfigurations: no configurations"); + usbi_err (HANDLE_CTX (dev_handle), "GetNumberOfConfigurations: no configurations"); return LIBUSB_ERROR_OTHER; } - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "device has %d configuration%s. using the first", + usbi_info (HANDLE_CTX (dev_handle), "device has %d configuration%s. using the first", (int)nConfig, (nConfig > 1 ? "s" : "") ); /* Always use the first configuration */ kresult = (*(dpriv->device))->GetConfigurationDescriptorPtr (dpriv->device, 0, &configDesc); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "GetConfigurationDescriptorPtr: %s", + usbi_err (HANDLE_CTX (dev_handle), "GetConfigurationDescriptorPtr: %s", darwin_error_str(kresult)); new_config = 1; } else new_config = configDesc->bConfigurationValue; - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "new configuration value is %d", new_config); + usbi_info (HANDLE_CTX (dev_handle), "new configuration value is %d", new_config); /* set the configuration */ kresult = darwin_set_configuration (dev_handle, new_config); if (kresult != LIBUSB_SUCCESS) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not set configuration"); + usbi_err (HANDLE_CTX (dev_handle), "could not set configuration"); return kresult; } kresult = darwin_get_interface (dpriv->device, iface, &usbInterface); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "darwin_get_interface: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } } if (!usbInterface) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "interface not found"); + usbi_err (HANDLE_CTX (dev_handle), "interface not found"); return LIBUSB_ERROR_NOT_FOUND; } @@ -857,12 +870,12 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i kresult = IOCreatePlugInInterfaceForService (usbInterface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &plugInInterface, &score); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "IOCreatePlugInInterfaceForService: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } if (!plugInInterface) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "plugin interface not found"); + usbi_err (HANDLE_CTX (dev_handle), "plugin interface not found"); return LIBUSB_ERROR_NOT_FOUND; } @@ -874,7 +887,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (LPVOID)&cInterface->interface); if (kresult || !cInterface->interface) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "QueryInterface: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "QueryInterface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -884,7 +897,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i /* claim the interface */ kresult = (*(cInterface->interface))->USBInterfaceOpen(cInterface->interface); if (kresult) { - _usbi_log(HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBInterfaceOpen: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceOpen: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -893,7 +906,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i if (kresult) { /* this should not happen */ darwin_release_interface (dev_handle, iface); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not build endpoint table"); + usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); return kresult; } @@ -902,7 +915,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i /* create async event source */ kresult = (*(cInterface->interface))->CreateInterfaceAsyncEventSource (cInterface->interface, &cInterface->cfSource); if (kresult != kIOReturnSuccess) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not create async event source"); + usbi_err (HANDLE_CTX (dev_handle), "could not create async event source"); /* can't continue without an async event source */ (void)darwin_release_interface (dev_handle, iface); @@ -913,7 +926,7 @@ static int darwin_claim_interface(struct libusb_device_handle *dev_handle, int i /* add the cfSource to the async thread's run loop */ CFRunLoopAddSource(libusb_darwin_acfl, cInterface->cfSource, kCFRunLoopDefaultMode); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_INFO, "interface opened"); + usbi_info (HANDLE_CTX (dev_handle), "interface opened"); return 0; } @@ -940,11 +953,11 @@ static int darwin_release_interface(struct libusb_device_handle *dev_handle, int kresult = (*(cInterface->interface))->USBInterfaceClose(cInterface->interface); if (kresult) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "USBInterfaceClose: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "USBInterfaceClose: %s", darwin_error_str(kresult)); kresult = (*(cInterface->interface))->Release(cInterface->interface); if (kresult != kIOReturnSuccess) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "Release: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "Release: %s", darwin_error_str(kresult)); cInterface->interface = IO_OBJECT_NULL; @@ -970,7 +983,7 @@ static int darwin_set_interface_altsetting(struct libusb_device_handle *dev_hand if (kresult) { /* this should not happen */ darwin_release_interface (dev_handle, iface); - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "could not build endpoint table"); + usbi_err (HANDLE_CTX (dev_handle), "could not build endpoint table"); return kresult; } @@ -987,7 +1000,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c /* determine the interface/endpoint to use */ if (ep_to_pipeRef (dev_handle, endpoint, &pipeRef, &iface) != 0) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (HANDLE_CTX (dev_handle), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } @@ -1001,7 +1014,7 @@ static int darwin_clear_halt(struct libusb_device_handle *dev_handle, unsigned c kresult = (*(cInterface->interface))->ClearPipeStallBothEnds(cInterface->interface, pipeRef); #endif if (kresult) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "ClearPipeStall: %s", darwin_error_str (kresult)); + usbi_err (HANDLE_CTX (dev_handle), "ClearPipeStall: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -1012,7 +1025,7 @@ static int darwin_reset_device(struct libusb_device_handle *dev_handle) { kresult = (*(dpriv->device))->ResetDevice (dpriv->device); if (kresult) - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "ResetDevice: %s", darwin_error_str (kresult)); + usbi_err (HANDLE_CTX (dev_handle), "ResetDevice: %s", darwin_error_str (kresult)); return darwin_to_libusb (kresult); } @@ -1025,7 +1038,7 @@ static int darwin_kernel_driver_active(struct libusb_device_handle *dev_handle, kresult = darwin_get_interface (dpriv->device, interface, &usbInterface); if (kresult) { - _usbi_log (HANDLE_CTX (dev_handle), LOG_LEVEL_ERROR, "darwin_get_interface: %s", darwin_error_str(kresult)); + usbi_err (HANDLE_CTX (dev_handle), "darwin_get_interface: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -1072,7 +1085,7 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { is_read = transfer->endpoint & LIBUSB_ENDPOINT_IN; if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } @@ -1103,8 +1116,8 @@ static int submit_bulk_transfer(struct usbi_transfer *itransfer) { } if (ret) - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "bulk transfer failed (dir = %s): %s", is_read ? "In" : "Out", - darwin_error_str(ret)); + usbi_err (TRANSFER_CTX (transfer), "bulk transfer failed (dir = %s): %s (code = 0x%08x)", is_read ? "In" : "Out", + darwin_error_str(ret), ret); return darwin_to_libusb (ret); } @@ -1137,7 +1150,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { /* determine the interface/endpoint to use */ if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } @@ -1147,7 +1160,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { /* Last but not least we need the bus frame number */ kresult = (*(cInterface->interface))->GetBusFrameNumber(cInterface->interface, &frame, &atTime); if (kresult) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "failed to get bus frame number: %d", kresult); + usbi_err (TRANSFER_CTX (transfer), "failed to get bus frame number: %d", kresult); free(tpriv->isoc_framelist); tpriv->isoc_framelist = NULL; @@ -1168,7 +1181,7 @@ static int submit_iso_transfer(struct usbi_transfer *itransfer) { itransfer); if (kresult != kIOReturnSuccess) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "isochronous transfer failed (dir: %s): %s", is_read ? "In" : "Out", + usbi_err (TRANSFER_CTX (transfer), "isochronous transfer failed (dir: %s): %s", is_read ? "In" : "Out", darwin_error_str(kresult)); free (tpriv->isoc_framelist); tpriv->isoc_framelist = NULL; @@ -1203,7 +1216,7 @@ static int submit_control_transfer(struct usbi_transfer *itransfer) { kresult = (*(dpriv->device))->DeviceRequestAsyncTO(dpriv->device, &(tpriv->req), darwin_async_io_callback, itransfer); if (kresult != kIOReturnSuccess) - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "control request failed: %s", darwin_error_str(kresult)); + usbi_err (TRANSFER_CTX (transfer), "control request failed: %s", darwin_error_str(kresult)); return darwin_to_libusb (kresult); } @@ -1220,7 +1233,7 @@ static int darwin_submit_transfer(struct usbi_transfer *itransfer) { case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: return submit_iso_transfer(itransfer); default: - _usbi_log (TRANSFER_CTX(transfer), LOG_LEVEL_ERROR, "unknown endpoint type %d", transfer->type); + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } } @@ -1230,7 +1243,7 @@ static int cancel_control_transfer(struct usbi_transfer *itransfer) { struct darwin_device_priv *dpriv = (struct darwin_device_priv *)transfer->dev_handle->dev->os_priv; IOReturn kresult; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "WARNING: aborting all transactions control pipe"); + usbi_info (ITRANSFER_CTX (itransfer), "WARNING: aborting all transactions control pipe"); kresult = (*(dpriv->device))->USBDeviceAbortPipeZero (dpriv->device); @@ -1245,19 +1258,19 @@ static int darwin_abort_transfers (struct usbi_transfer *itransfer) { IOReturn kresult; if (ep_to_pipeRef (transfer->dev_handle, transfer->endpoint, &pipeRef, &iface) != 0) { - _usbi_log (TRANSFER_CTX (transfer), LOG_LEVEL_ERROR, "endpoint not found on any open interface"); + usbi_err (TRANSFER_CTX (transfer), "endpoint not found on any open interface"); return LIBUSB_ERROR_NOT_FOUND; } cInterface = &priv->interfaces[iface]; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "WARNING: aborting all transactions on interface %d pipe %d", iface, pipeRef); + usbi_info (ITRANSFER_CTX (itransfer), "WARNING: aborting all transactions on interface %d pipe %d", iface, pipeRef); /* abort transactions */ (*(cInterface->interface))->AbortPipe (cInterface->interface, pipeRef); - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "calling clear pipe stall to clear the data toggle bit"); + usbi_info (ITRANSFER_CTX (itransfer), "calling clear pipe stall to clear the data toggle bit"); /* clear the data toggle bit */ #if (InterfaceVersion < 190) @@ -1281,7 +1294,7 @@ static int darwin_cancel_transfer(struct usbi_transfer *itransfer) { case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: return darwin_abort_transfers (itransfer); default: - _usbi_log (TRANSFER_CTX(transfer), LOG_LEVEL_ERROR, "unknown endpoint type %d", transfer->type); + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); return LIBUSB_ERROR_INVALID_PARAM; } } @@ -1302,7 +1315,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) struct darwin_device_handle_priv *priv = (struct darwin_device_handle_priv *)transfer->dev_handle->os_priv; UInt32 message; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "an async io operation has completed"); + usbi_info (ITRANSFER_CTX (itransfer), "an async io operation has completed"); /* send a completion message to the device's file descriptor */ message = MESSAGE_ASYNC_IO_COMPLETE; @@ -1315,7 +1328,7 @@ static void darwin_async_io_callback (void *refcon, IOReturn result, void *arg0) static void darwin_bulk_callback (struct usbi_transfer *itransfer, kern_return_t result, UInt32 io_size) { enum libusb_transfer_status status; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "handling bulk completion with status %d", result); + usbi_info (ITRANSFER_CTX (itransfer), "handling bulk completion with status %d", result); switch (result) { case kIOReturnSuccess: @@ -1326,17 +1339,17 @@ static void darwin_bulk_callback (struct usbi_transfer *itransfer, kern_return_t usbi_handle_transfer_cancellation(itransfer); return; case kIOUSBPipeStalled: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_WARNING, "bulk error. pipe is stalled"); + usbi_warn (ITRANSFER_CTX (itransfer), "bulk error. pipe is stalled"); status = LIBUSB_TRANSFER_STALL; break; case kIOReturnOverrun: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "bulk error. data overrun", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "bulk error. data overrun", darwin_error_str (result)); status = LIBUSB_TRANSFER_OVERFLOW; break; default: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "bulk error = %s (value = 0x%08x)", darwin_error_str (result), result); + usbi_err (ITRANSFER_CTX (itransfer), "bulk error = %s (value = 0x%08x)", darwin_error_str (result), result); status = LIBUSB_TRANSFER_ERROR; } @@ -1348,7 +1361,7 @@ static void darwin_isoc_callback (struct usbi_transfer *itransfer, kern_return_t struct darwin_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); int i, status; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "handling isoc completion with status %d", result); + usbi_info (ITRANSFER_CTX (itransfer), "handling isoc completion with status %d", result); if (result == kIOReturnSuccess && tpriv->isoc_framelist) { /* copy isochronous results back */ @@ -1368,17 +1381,17 @@ static void darwin_isoc_callback (struct usbi_transfer *itransfer, kern_return_t usbi_handle_transfer_cancellation(itransfer); return; case kIOUSBPipeStalled: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_WARNING, "unsupported control request"); + usbi_warn (ITRANSFER_CTX (itransfer), "unsupported control request"); status = LIBUSB_TRANSFER_STALL; break; case kIOReturnOverrun: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "bulk error. data overrun", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "bulk error. data overrun", darwin_error_str (result)); status = LIBUSB_TRANSFER_OVERFLOW; break; default: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "control error = %s", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "control error = %s", darwin_error_str (result)); status = LIBUSB_TRANSFER_ERROR; } @@ -1388,7 +1401,7 @@ static void darwin_isoc_callback (struct usbi_transfer *itransfer, kern_return_t static void darwin_control_callback (struct usbi_transfer *itransfer, kern_return_t result, UInt32 io_size) { int status; - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_INFO, "handling control completion with status %d", result); + usbi_info (ITRANSFER_CTX (itransfer), "handling control completion with status %d", result); switch (result) { case kIOReturnSuccess: @@ -1399,12 +1412,12 @@ static void darwin_control_callback (struct usbi_transfer *itransfer, kern_retur usbi_handle_transfer_cancellation(itransfer); return; case kIOUSBPipeStalled: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_WARNING, "unsupported control request"); + usbi_warn (ITRANSFER_CTX (itransfer), "unsupported control request"); status = LIBUSB_TRANSFER_STALL; break; default: - _usbi_log (ITRANSFER_CTX (itransfer), LOG_LEVEL_ERROR, "control error = %s", darwin_error_str (result)); + usbi_err (ITRANSFER_CTX (itransfer), "control error = %s", darwin_error_str (result)); status = LIBUSB_TRANSFER_ERROR; } @@ -1426,7 +1439,7 @@ static void darwin_handle_callback (struct usbi_transfer *itransfer, kern_return darwin_isoc_callback (itransfer, result); break; default: - _usbi_log (TRANSFER_CTX(transfer), LOG_LEVEL_ERROR, "unknown endpoint type %d", transfer->type); + usbi_err (TRANSFER_CTX(transfer), "unknown endpoint type %d", transfer->type); } } @@ -1437,13 +1450,13 @@ static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds int i = 0, ret; UInt32 message; - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { struct pollfd *pollfd = &fds[i]; struct libusb_device_handle *handle; struct darwin_device_handle_priv *hpriv = NULL; - _usbi_log (ctx, LOG_LEVEL_INFO, "checking fd %i with revents = %x", fds[i], pollfd->revents); + usbi_info (ctx, "checking fd %i with revents = %x", fds[i], pollfd->revents); if (!pollfd->revents) continue; @@ -1486,11 +1499,11 @@ static int op_handle_events(struct libusb_context *ctx, struct pollfd *fds, nfds darwin_handle_callback (itransfer, kresult, io_size); break; default: - _usbi_log (ctx, LOG_LEVEL_ERROR, "unknown message received from device pipe"); + usbi_err (ctx, "unknown message received from device pipe"); } } - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); return 0; } diff --git a/libusb/os/linux_usbfs.c b/libusb/os/linux_usbfs.c index 3888aa9..dd38e65 100644 --- a/libusb/os/linux_usbfs.c +++ b/libusb/os/linux_usbfs.c @@ -1775,7 +1775,7 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer, enum libusb_transfer_status status = LIBUSB_TRANSFER_COMPLETED; int r = 0; - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); usbi_dbg("handling completion status %d of bulk urb %d/%d", urb->status, urb_idx + 1, num_urbs); @@ -1819,7 +1819,7 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer, if (tpriv->reap_action == CANCELLED) { free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); r = usbi_handle_transfer_cancellation(itransfer); goto out_unlock; } @@ -1897,10 +1897,10 @@ static int handle_bulk_completion(struct usbi_transfer *itransfer, completed: free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, status); out_unlock: - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return r; } @@ -1914,7 +1914,7 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, int urb_idx = 0; int i; - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); for (i = 0; i < num_urbs; i++) { if (urb == tpriv->iso_urbs[i]) { urb_idx = i + 1; @@ -1923,7 +1923,7 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, } if (urb_idx == 0) { usbi_err(TRANSFER_CTX(transfer), "could not locate urb!"); - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return LIBUSB_ERROR_NOT_FOUND; } @@ -1951,10 +1951,10 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, usbi_dbg("CANCEL: last URB handled, reporting"); free_iso_urbs(tpriv); if (tpriv->reap_action == CANCELLED) { - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_cancellation(itransfer); } else { - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_ERROR); } @@ -1981,12 +1981,12 @@ static int handle_iso_completion(struct usbi_transfer *itransfer, if (urb_idx == num_urbs) { usbi_dbg("last URB in transfer --> complete!"); free_iso_urbs(tpriv); - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, LIBUSB_TRANSFER_COMPLETED); } out: - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return 0; } @@ -1996,7 +1996,7 @@ static int handle_control_completion(struct usbi_transfer *itransfer, struct linux_transfer_priv *tpriv = usbi_transfer_get_os_priv(itransfer); int status; - pthread_mutex_lock(&itransfer->lock); + usbi_mutex_lock(&itransfer->lock); usbi_dbg("handling completion status %d", urb->status); if (urb->status == 0) @@ -2008,7 +2008,7 @@ static int handle_control_completion(struct usbi_transfer *itransfer, "cancel: unrecognised urb status %d", urb->status); free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_cancellation(itransfer); } @@ -2036,7 +2036,7 @@ static int handle_control_completion(struct usbi_transfer *itransfer, free(tpriv->urbs); tpriv->urbs = NULL; - pthread_mutex_unlock(&itransfer->lock); + usbi_mutex_unlock(&itransfer->lock); return usbi_handle_transfer_completion(itransfer, status); } @@ -2087,7 +2087,7 @@ static int op_handle_events(struct libusb_context *ctx, int r; int i = 0; - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { struct pollfd *pollfd = &fds[i]; struct libusb_device_handle *handle; @@ -2118,7 +2118,7 @@ static int op_handle_events(struct libusb_context *ctx, r = 0; out: - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); return r; } diff --git a/libusb/os/sources b/libusb/os/sources index c4d0163..669e32a 100644 --- a/libusb/os/sources +++ b/libusb/os/sources @@ -7,12 +7,6 @@ DLLDEF=..\libusb-1.0.def MSC_WARNING_LEVEL=/W3 !ENDIF -!IF "$(_BUILDARCH)"=="AMD64" -PTHREAD_LIB=pthreadVC2_x64.lib -!ELSE -PTHREAD_LIB=pthreadVC2.lib -!ENDIF - USE_MSVCRT=1 INCLUDES=..;..\..;..\..\msvc;$(DDK_INC_PATH) @@ -22,13 +16,13 @@ TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib \ $(SDK_LIB_PATH)\advapi32.lib \ $(SDK_LIB_PATH)\user32.lib \ $(SDK_LIB_PATH)\setupapi.lib \ - $(SDK_LIB_PATH)\ole32.lib \ - ..\..\msvc\$(PTHREAD_LIB) + $(SDK_LIB_PATH)\ole32.lib SOURCES=..\core.c \ ..\descriptor.c \ ..\io.c \ ..\sync.c \ + threads_windows.c \ windows_compat.c \ windows_usb.c \ libusb-1.0.rc diff --git a/libusb/os/threads_posix.h b/libusb/os/threads_posix.h new file mode 100644 index 0000000..7e34dc5 --- /dev/null +++ b/libusb/os/threads_posix.h @@ -0,0 +1,46 @@ +/* + * libusb synchronization using POSIX Threads + * + * Copyright (C) 2010 Peter Stuge <peter@stuge.se> + * + * 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_THREADS_POSIX_H__ +#define __LIBUSB_THREADS_POSIX_H__ + +#include <pthread.h> + +#define usbi_mutex_static_t static pthread_mutex_t +#define USBI_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define usbi_mutex_static_lock pthread_mutex_lock +#define usbi_mutex_static_unlock pthread_mutex_unlock + +#define usbi_mutex_t pthread_mutex_t +#define usbi_mutex_init pthread_mutex_init +#define usbi_mutex_lock pthread_mutex_lock +#define usbi_mutex_unlock pthread_mutex_unlock +#define usbi_mutex_trylock pthread_mutex_trylock +#define usbi_mutex_destroy pthread_mutex_destroy + +#define usbi_cond_t pthread_cond_t +#define usbi_cond_init pthread_cond_init +#define usbi_cond_wait pthread_cond_wait +#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 + +#endif /* __LIBUSB_THREADS_POSIX_H__ */ diff --git a/libusb/os/threads_windows.c b/libusb/os/threads_windows.c new file mode 100644 index 0000000..f0704b2 --- /dev/null +++ b/libusb/os/threads_windows.c @@ -0,0 +1,207 @@ +/* + * libusb synchronization on Microsoft Windows + * + * Copyright (C) 2010 Michael Plante <michael.plante@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <config.h> +#include <objbase.h> +#include <errno.h> +#include <stdarg.h> + +#include "libusb.h" +#include "libusbi.h" + + +int usbi_mutex_init(usbi_mutex_t *mutex, + const usbi_mutexattr_t *attr) { + if(! mutex) return ((errno=EINVAL)); + *mutex = CreateMutex(NULL, FALSE, NULL); + if(!*mutex) return ((errno=ENOMEM)); + return 0; +} +int usbi_mutex_destroy(usbi_mutex_t *mutex) { + // It is not clear if CloseHandle failure is due to failure to unlock. + // If so, this should be errno=EBUSY. + if(!mutex || !CloseHandle(*mutex)) return ((errno=EINVAL)); + *mutex = NULL; + return 0; +} +int usbi_mutex_trylock(usbi_mutex_t *mutex) { + DWORD result; + if(!mutex) return ((errno=EINVAL)); + result = WaitForSingleObject(*mutex, 0); + if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) + return 0; // acquired (ToDo: check that abandoned is ok) + if(result == WAIT_TIMEOUT) + return ((errno=EBUSY)); + return ((errno=EINVAL)); // don't know how this would happen + // so don't know proper errno +} +int usbi_mutex_lock(usbi_mutex_t *mutex) { + DWORD result; + if(!mutex) return ((errno=EINVAL)); + result = WaitForSingleObject(*mutex, INFINITE); + if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED) + return 0; // acquired (ToDo: check that abandoned is ok) + return ((errno=EINVAL)); // don't know how this would happen + // so don't know proper errno +} +int usbi_mutex_unlock(usbi_mutex_t *mutex) { + if(!mutex) return ((errno=EINVAL)); + if(!ReleaseMutex(mutex)) return ((errno=EPERM )); + return 0; +} + +int usbi_mutex_static_lock(usbi_mutex_static_t *mutex) { + if(!mutex) return ((errno=EINVAL)); + while (InterlockedExchange((LONG *)mutex, 1) == 1) { + SleepEx(0, TRUE); + } + return 0; +} +int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex) { + if(!mutex) return ((errno=EINVAL)); + *mutex = 0; + return 0; +} + + + +int usbi_cond_init(usbi_cond_t *cond, + const usbi_condattr_t *attr) { + if(!cond) return ((errno=EINVAL)); + list_init(&cond->waiters ); + list_init(&cond->not_waiting); + return 0; +} +int usbi_cond_destroy(usbi_cond_t *cond) { + // This assumes no one is using this anymore. The check MAY NOT BE safe. + struct usbi_cond_perthread *pos, *prev_pos = NULL; + if(!cond) return ((errno=EINVAL)); + if(!list_empty(&cond->waiters)) return ((errno=EBUSY )); // (!see above!) + list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) { + free(prev_pos); + list_del(&pos->list); + prev_pos = pos; + } + free(prev_pos); + prev_pos = pos = NULL; + + return 0; +} + +int usbi_cond_broadcast(usbi_cond_t *cond) { + // Assumes mutex is locked; this is not in keeping with POSIX spec, but + // libusb does this anyway, so we simplify by not adding more sync + // primitives to the CV definition! + int fail = 0; + struct usbi_cond_perthread *pos; + if(!cond) return ((errno=EINVAL)); + list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread) { + if(!SetEvent(pos->event)) + fail = 1; + } + // The wait function will remove its respective item from the list. + return fail ? ((errno=EINVAL)) : 0; +} +int usbi_cond_signal(usbi_cond_t *cond) { + // Assumes mutex is locked; this is not in keeping with POSIX spec, but + // libusb does this anyway, so we simplify by not adding more sync + // primitives to the CV definition! + struct usbi_cond_perthread *pos; + if(!cond) return ((errno=EINVAL)); + if(list_empty(&cond->waiters)) return 0; // no one to wakeup. + pos = list_entry(&cond->waiters.next, struct usbi_cond_perthread, list); + // The wait function will remove its respective item from the list. + return SetEvent(pos->event) ? 0 : ((errno=EINVAL)); +} +static int __inline usbi_cond_intwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, + DWORD timeout_ms) { + struct usbi_cond_perthread *pos; + int found = 0, r; + DWORD r2,tid = GetCurrentThreadId(); + if(!cond || !mutex) return ((errno=EINVAL)); + list_for_each_entry(pos, &cond->not_waiting, list, struct usbi_cond_perthread) { + if(tid == pos->tid) { + found = 1; + break; + } + } + if(!found) { + pos = malloc(sizeof(struct usbi_cond_perthread)); + if(!pos) return ((errno=ENOMEM)); // This errno is not POSIX-allowed. + pos->tid = tid; + pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset. + if(!pos->event) { + free(pos); + return ((errno=ENOMEM)); + } + list_add(&pos->list, &cond->not_waiting); + } + + list_del(&pos->list); // remove from not_waiting list. + list_add(&pos->list, &cond->waiters); + + r = usbi_mutex_unlock(mutex); + if(r) return r; + r2 = WaitForSingleObject(pos->event, timeout_ms); + r = usbi_mutex_lock(mutex); + if(r) return r; + + list_del(&pos->list); + list_add(&pos->list, &cond->not_waiting); + + if(r2 == WAIT_TIMEOUT) return ((errno=ETIMEDOUT)); + + return 0; +} +// N.B.: usbi_cond_*wait() can also return ENOMEM, even though pthread_cond_*wait cannot! +int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex) { + return usbi_cond_intwait(cond, mutex, INFINITE); +} +int usbi_cond_timedwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, + const struct timespec *abstime) { + FILETIME ftime; + ULARGE_INTEGER rtime; + struct timeval targ_time, cur_time, delta_time; + struct timespec cur_time_ns; + DWORD millis; + extern const uint64_t epoch_time; + + GetSystemTimeAsFileTime(&ftime); + rtime.LowPart = ftime.dwLowDateTime; + rtime.HighPart = ftime.dwHighDateTime; + rtime.QuadPart -= epoch_time; + cur_time_ns.tv_sec = (long)(rtime.QuadPart / 10000000); + cur_time_ns.tv_nsec = (long)((rtime.QuadPart % 10000000)*100); + TIMESPEC_TO_TIMEVAL(&cur_time, &cur_time_ns); + + TIMESPEC_TO_TIMEVAL(&targ_time, abstime); + timersub(&targ_time, &cur_time, &delta_time); + if(delta_time.tv_sec <= 0) // abstime already passed? + millis = 0; + else { + millis = delta_time.tv_usec/1000; + millis += delta_time.tv_sec *1000; + } + + return usbi_cond_intwait(cond, mutex, millis); +} + diff --git a/libusb/os/threads_windows.h b/libusb/os/threads_windows.h new file mode 100644 index 0000000..52ae9c1 --- /dev/null +++ b/libusb/os/threads_windows.h @@ -0,0 +1,83 @@ +/* + * libusb synchronization on Microsoft Windows + * + * Copyright (C) 2010 Michael Plante <michael.plante@gmail.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __LIBUSB_THREADS_WINDOWS_H__ +#define __LIBUSB_THREADS_WINDOWS_H__ + +#define usbi_mutex_static_t volatile LONG +#define USBI_MUTEX_INITIALIZER 0 + +#define usbi_mutex_t HANDLE + +struct usbi_cond_perthread { + struct list_head list; + DWORD tid; + HANDLE event; +}; +struct usbi_cond_t_ { + // Every time a thread touches the CV, it winds up in one of these lists. + // It stays there until the CV is destroyed, even if the thread + // terminates. + struct list_head waiters; + struct list_head not_waiting; +}; +typedef struct usbi_cond_t_ usbi_cond_t; + +// We *were* getting timespec from pthread.h: +#ifndef HAVE_STRUCT_TIMESPEC +#define HAVE_STRUCT_TIMESPEC 1 +struct timespec { + long tv_sec; + long tv_nsec; +}; +#endif /* HAVE_STRUCT_TIMESPEC */ + +// We *were* getting ETIMEDOUT from pthread.h: +#ifndef ETIMEDOUT +# define ETIMEDOUT 10060 /* This is the value in winsock.h. */ +#endif + +#define usbi_mutexattr_t void +#define usbi_condattr_t void + + +int usbi_mutex_static_lock(usbi_mutex_static_t *mutex); +int usbi_mutex_static_unlock(usbi_mutex_static_t *mutex); + + +int usbi_mutex_init(usbi_mutex_t *mutex, + const usbi_mutexattr_t *attr); +int usbi_mutex_lock(usbi_mutex_t *mutex); +int usbi_mutex_unlock(usbi_mutex_t *mutex); +int usbi_mutex_trylock(usbi_mutex_t *mutex); +int usbi_mutex_destroy(usbi_mutex_t *mutex); + +int usbi_cond_init(usbi_cond_t *cond, + const usbi_condattr_t *attr); +int usbi_cond_destroy(usbi_cond_t *cond); +int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex); +int usbi_cond_timedwait(usbi_cond_t *cond, + usbi_mutex_t *mutex, + const struct timespec *abstime); +int usbi_cond_broadcast(usbi_cond_t *cond); +int usbi_cond_signal(usbi_cond_t *cond); + +#endif /* __LIBUSB_THREADS_WINDOWS_H__ */ + diff --git a/libusb/os/windows_compat.c b/libusb/os/windows_compat.c index 9b74d35..bd5a948 100644 --- a/libusb/os/windows_compat.c +++ b/libusb/os/windows_compat.c @@ -68,7 +68,7 @@ #include <stdint.h> #include <io.h> -#include "windows_compat.h" +#include "libusbi.h" // Uncomment to debug the polling layer //#define DEBUG_WINDOWS_COMPAT @@ -88,7 +88,7 @@ #pragma warning(disable:28719) #endif -#if defined(__CYGWIN__ ) +#if defined(__CYGWIN__) // cygwin produces a warning unless these prototypes are defined extern int _close(int fd); extern int _snprintf(char *buffer, size_t count, const char *format, ...); diff --git a/libusb/os/windows_compat.h b/libusb/os/windows_compat.h index 322ce78..12de260 100644 --- a/libusb/os/windows_compat.h +++ b/libusb/os/windows_compat.h @@ -43,6 +43,7 @@ extern enum windows_version windows_version; #define MAX_FDS 256 +#if !defined(__CYGWIN__) #define POLLIN 0x0001 /* There is data to read */ #define POLLPRI 0x0002 /* There is urgent data to read */ #define POLLOUT 0x0004 /* Writing now will not block */ @@ -55,6 +56,7 @@ struct pollfd { short events; /* requested events */ short revents; /* returned events */ }; +#endif typedef unsigned int nfds_t; // access modes @@ -129,3 +131,4 @@ do { \ } \ } while (0) #endif + diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index dae05ef..f6a0796 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -35,11 +35,7 @@ // ***USE AT YOUR OWN RISKS*** //#define FORCE_INSTANT_TIMEOUTS -#if defined(_MSC_VER) -#include <config_msvc.h> -#else #include <config.h> -#endif #include <windows.h> #include <setupapi.h> #include <ctype.h> @@ -1876,7 +1872,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, struct usbi_transfer *transfer; DWORD io_size, io_result; - pthread_mutex_lock(&ctx->open_devs_lock); + usbi_mutex_lock(&ctx->open_devs_lock); for (i = 0; i < nfds && num_ready > 0; i++) { usbi_dbg("checking fd %d with revents = %04x", fds[i].fd, fds[i].revents); @@ -1918,7 +1914,7 @@ static int windows_handle_events(struct libusb_context *ctx, struct pollfd *fds, } } - pthread_mutex_unlock(&ctx->open_devs_lock); + usbi_mutex_unlock(&ctx->open_devs_lock); return LIBUSB_SUCCESS; } |