static void wince_exit(void) { HANDLE semaphore; TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); semaphore = CreateSemaphore(NULL, 1, 1, sem_name); if (semaphore == NULL) return; // A successful wait brings our semaphore count to 0 (unsignaled) // => any concurent wait stalls until the semaphore release if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { CloseHandle(semaphore); return; } // Only works if exits and inits are balanced exactly if (--concurrent_usage < 0) { // Last exit exit_dllimports(); exit_polling(); if (driver_handle != INVALID_HANDLE_VALUE) { UkwCloseDriver(driver_handle); driver_handle = INVALID_HANDLE_VALUE; } } ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 CloseHandle(semaphore); }
static int usbdk_init(struct libusb_context *ctx) { int r; if (++concurrent_usage == 0) { // First init? r = load_usbdk_helper_dll(ctx); if (r) goto init_exit; init_polling(); r = windows_common_init(ctx); if (r) goto init_exit; } // At this stage, either we went through full init successfully, or didn't need to r = LIBUSB_SUCCESS; init_exit: if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? exit_polling(); windows_common_exit(); unload_usbdk_helper_dll(); } if (r != LIBUSB_SUCCESS) --concurrent_usage; // Not expected to call libusb_exit if we failed. return r; }
static void usbdk_exit(void) { if (--concurrent_usage < 0) { windows_common_exit(); exit_polling(); unload_usbdk_helper_dll(); } }
static void wince_exit(void) { int i; HANDLE semaphore; TCHAR sem_name[11+1+8]; // strlen(libusb_init)+'\0'+(32-bit hex PID) _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)GetCurrentProcessId()&0xFFFFFFFF); semaphore = CreateSemaphore(NULL, 1, 1, sem_name); if (semaphore == NULL) { return; } // A successful wait brings our semaphore count to 0 (unsignaled) // => any concurent wait stalls until the semaphore release if (WaitForSingleObject(semaphore, INFINITE) != WAIT_OBJECT_0) { CloseHandle(semaphore); return; } // Only works if exits and inits are balanced exactly if (--concurrent_usage < 0) { // Last exit exit_polling(); if (timer_thread) { SetEvent(timer_request[1]); // actually the signal to quit the thread. if (WAIT_OBJECT_0 != WaitForSingleObject(timer_thread, INFINITE)) { usbi_dbg("could not wait for timer thread to quit"); TerminateThread(timer_thread, 1); } CloseHandle(timer_thread); timer_thread = NULL; } for (i = 0; i < 2; i++) { if (timer_request[i]) { CloseHandle(timer_request[i]); timer_request[i] = NULL; } } if (timer_response) { CloseHandle(timer_response); timer_response = NULL; } if (timer_mutex) { CloseHandle(timer_mutex); timer_mutex = NULL; } if (driver_handle != INVALID_HANDLE_VALUE) { UkwCloseDriver(driver_handle); driver_handle = INVALID_HANDLE_VALUE; } } ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 CloseHandle(semaphore); }
// Internal API functions static int wince_init(struct libusb_context *ctx) { int r = LIBUSB_ERROR_OTHER; HANDLE semaphore; LARGE_INTEGER li_frequency; TCHAR sem_name[11 + 8 + 1]; // strlen("libusb_init") + (32-bit hex PID) + '\0' _stprintf(sem_name, _T("libusb_init%08X"), (unsigned int)(GetCurrentProcessId() & 0xFFFFFFFF)); semaphore = CreateSemaphore(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 ( ++concurrent_usage == 0 ) { // First init? // Initialize pollable file descriptors init_polling(); // Load DLL imports if (init_dllimports() != LIBUSB_SUCCESS) { usbi_err(ctx, "could not resolve DLL functions"); r = LIBUSB_ERROR_NOT_SUPPORTED; goto init_exit; } // try to open a handle to the driver driver_handle = UkwOpenDriver(); if (driver_handle == INVALID_HANDLE_VALUE) { usbi_err(ctx, "could not connect to driver"); r = LIBUSB_ERROR_NOT_SUPPORTED; goto init_exit; } // find out if we have access to a monotonic (hires) timer if (QueryPerformanceFrequency(&li_frequency)) { hires_frequency = li_frequency.QuadPart; // The hires frequency can go as high as 4 GHz, so we'll use a conversion // to picoseconds to compute the tv_nsecs part in clock_gettime hires_ticks_to_ps = UINT64_C(1000000000000) / hires_frequency; usbi_dbg("hires timer available (Frequency: %"PRIu64" Hz)", hires_frequency); } else { usbi_dbg("no hires timer available on this platform"); hires_frequency = 0; hires_ticks_to_ps = UINT64_C(0); } } // At this stage, either we went through full init successfully, or didn't need to r = LIBUSB_SUCCESS; init_exit: // Holds semaphore here. if (!concurrent_usage && r != LIBUSB_SUCCESS) { // First init failed? exit_dllimports(); exit_polling(); if (driver_handle != INVALID_HANDLE_VALUE) { UkwCloseDriver(driver_handle); driver_handle = INVALID_HANDLE_VALUE; } } if (r != LIBUSB_SUCCESS) --concurrent_usage; // Not expected to call libusb_exit if we failed. ReleaseSemaphore(semaphore, 1, NULL); // increase count back to 1 CloseHandle(semaphore); return r; }