API_EXPORTED usb_dev_handle *usb_open(struct usb_device *dev) { int r; usbi_dbg(""); usb_dev_handle *udev = malloc(sizeof(*udev)); if (!udev) return NULL; r = libusb_open((libusb_device *) dev->dev, &udev->handle); if (r < 0) { if (r == LIBUSB_ERROR_ACCESS) { usbi_info("Device open failed due to a permission denied error."); usbi_info("libusb requires write access to USB device nodes."); } usbi_err("could not open device, error %d", r); free(udev); errno = libusb_to_errno(r); return NULL; } udev->last_claimed_interface = -1; udev->device = dev; return udev; }
static int windows_init(struct libusb_context *ctx) { struct windows_context_priv *priv = _context_priv(ctx); HANDLE semaphore; char sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' int r = LIBUSB_ERROR_OTHER; bool winusb_backend_init = false; sprintf(sem_name, "libusb_init%08X", (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); semaphore = CreateSemaphoreA(NULL, 1, 1, sem_name); if (semaphore == NULL) { usbi_err(ctx, "could not create semaphore: %s", windows_error_str(0)); return LIBUSB_ERROR_NO_MEM; } // A successful wait brings our semaphore count to 0 (unsignaled) // => any concurent wait stalls until the semaphore's release if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { usbi_err(ctx, "failure to access semaphore: %s", windows_error_str(0)); CloseHandle(semaphore); return LIBUSB_ERROR_NO_MEM; } // NB: concurrent usage supposes that init calls are equally balanced with // exit calls. If init is called more than exit, we will not exit properly if (++init_count == 1) { // First init? // Load DLL imports if (!windows_init_dlls()) { usbi_err(ctx, "could not resolve DLL functions"); goto init_exit; } get_windows_version(); if (windows_version == WINDOWS_UNDEFINED) { usbi_err(ctx, "failed to detect Windows version"); r = LIBUSB_ERROR_NOT_SUPPORTED; goto init_exit; } if (!windows_init_clock(ctx)) goto init_exit; if (!htab_create(ctx)) goto init_exit; r = winusb_backend.init(ctx); if (r != LIBUSB_SUCCESS) goto init_exit; winusb_backend_init = true; r = usbdk_backend.init(ctx); if (r == LIBUSB_SUCCESS) { usbi_dbg("UsbDk backend is available"); usbdk_available = true; } else { usbi_info(ctx, "UsbDk backend is not available"); // Do not report this as an error r = LIBUSB_SUCCESS; } } // By default, new contexts will use the WinUSB backend priv->backend = &winusb_backend; r = LIBUSB_SUCCESS; init_exit: // Holds semaphore here if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed? if (winusb_backend_init) winusb_backend.exit(ctx); htab_destroy(); windows_destroy_clock(); windows_exit_dlls(); --init_count; } ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 CloseHandle(semaphore); return r; }