Skip to content
Permalink
Browse files

Windows: Drop support for Windows XP

XP is nearly 20 years old and there are hoops we jump through to keep
supporting it. Time to say goodbye and simplify some things.

Closes #267

Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
  • Loading branch information
dickens committed Jan 22, 2020
1 parent 1816288 commit 96e0af79b383fa805dd4bff1e4f8bebe3c6fdb46
@@ -178,8 +178,7 @@ windows)
LIBS=""
LTLDFLAGS="${LTLDFLAGS} -avoid-version -Wl,--add-stdcall-alias"
AC_DEFINE([POLL_NFDS_TYPE],[unsigned int],[type of second poll() argument])
AC_DEFINE([WINVER], 0x0501, [Oldest Windows version supported])
AC_DEFINE([_WIN32_WINNT], 0x0501, [Oldest Windows version supported])
AC_DEFINE([_WIN32_WINNT], [_WIN32_WINNT_VISTA], [Oldest Windows version supported (Vista)])
;;
haiku)
AC_DEFINE(OS_HAIKU, 1, [Haiku backend])
@@ -2,6 +2,7 @@
* libusb synchronization on Microsoft Windows
*
* Copyright © 2010 Michael Plante <michael.plante@gmail.com>
* Copyright © 2020 Chris Dickens <christopher.a.dickens@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,97 +25,20 @@

#include "libusbi.h"

struct usbi_cond_perthread {
struct list_head list;
HANDLE event;
};

void usbi_cond_init(usbi_cond_t *cond)
{
list_init(&cond->waiters);
list_init(&cond->not_waiting);
}

static int usbi_cond_intwait(usbi_cond_t *cond,
usbi_mutex_t *mutex, DWORD timeout_ms)
{
struct usbi_cond_perthread *pos;
DWORD r;

// Same assumption as usbi_cond_broadcast() holds
if (list_empty(&cond->not_waiting)) {
pos = malloc(sizeof(*pos));
if (pos == NULL)
return ENOMEM; // This errno is not POSIX-allowed.
pos->event = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset.
if (pos->event == NULL) {
free(pos);
return ENOMEM;
}
} else {
pos = list_first_entry(&cond->not_waiting, struct usbi_cond_perthread, list);
list_del(&pos->list); // remove from not_waiting list.
// Ensure the event is clear before waiting
WaitForSingleObject(pos->event, 0);
}

list_add(&pos->list, &cond->waiters);

LeaveCriticalSection(mutex);
r = WaitForSingleObject(pos->event, timeout_ms);
EnterCriticalSection(mutex);

list_del(&pos->list);
list_add(&pos->list, &cond->not_waiting);

if (r == WAIT_OBJECT_0)
return 0;
else if (r == WAIT_TIMEOUT)
return ETIMEDOUT;
else
return EINVAL;
}

// 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 timeval *tv)
{
DWORD millis;

millis = (DWORD)(tv->tv_sec * 1000) + (tv->tv_usec / 1000);
millis = (DWORD)(tv->tv_sec * 1000L) + (tv->tv_usec / 1000L);
/* round up to next millisecond */
if (tv->tv_usec % 1000)
if (tv->tv_usec % 1000L)
millis++;
return usbi_cond_intwait(cond, mutex, millis);
}

void 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!
struct usbi_cond_perthread *pos;

list_for_each_entry(pos, &cond->waiters, list, struct usbi_cond_perthread)
SetEvent(pos->event);
// The wait function will remove its respective item from the list.
}

void 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, *next;

if (!list_empty(&cond->waiters))
return; // (!see above!)
list_for_each_entry_safe(pos, next, &cond->not_waiting, list, struct usbi_cond_perthread) {
CloseHandle(pos->event);
list_del(&pos->list);
free(pos);
}
}
if (SleepConditionVariableCS(cond, mutex, millis))
return 0;
else if (GetLastError() == ERROR_TIMEOUT)
return ETIMEDOUT;
else
return EINVAL;
}
@@ -57,7 +57,7 @@ static inline void usbi_mutex_destroy(usbi_mutex_t *mutex)
}

// We *were* getting timespec from pthread.h:
#if (!defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED))
#if !defined(HAVE_STRUCT_TIMESPEC) && !defined(_TIMESPEC_DEFINED)
#define HAVE_STRUCT_TIMESPEC 1
#define _TIMESPEC_DEFINED 1
struct timespec {
@@ -71,19 +71,25 @@ struct timespec {
#define ETIMEDOUT 10060 /* This is the value in winsock.h. */
#endif

typedef struct usbi_cond {
// 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;
} usbi_cond_t;

void usbi_cond_init(usbi_cond_t *cond);
int usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex);
typedef CONDITION_VARIABLE usbi_cond_t;
static inline void usbi_cond_init(usbi_cond_t *cond)
{
InitializeConditionVariable(cond);
}
static inline void usbi_cond_wait(usbi_cond_t *cond, usbi_mutex_t *mutex)
{
(void)SleepConditionVariableCS(cond, mutex, INFINITE);
}
int usbi_cond_timedwait(usbi_cond_t *cond,
usbi_mutex_t *mutex, const struct timeval *tv);
void usbi_cond_broadcast(usbi_cond_t *cond);
void usbi_cond_destroy(usbi_cond_t *cond);
static inline void usbi_cond_broadcast(usbi_cond_t *cond)
{
WakeAllConditionVariable(cond);
}
static inline void usbi_cond_destroy(usbi_cond_t *cond)
{
UNUSED(cond);
}

typedef DWORD usbi_tls_key_t;
static inline void usbi_tls_key_create(usbi_tls_key_t *key)
@@ -34,7 +34,6 @@
#define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime

// Public
BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED);
enum windows_version windows_version = WINDOWS_UNDEFINED;

// Global variables for init/exit
@@ -59,11 +58,6 @@ struct timer_request {
static HANDLE timer_thread = NULL;
static DWORD timer_thread_id = 0;

/* Kernel32 dependencies */
DLL_DECLARE_HANDLE(Kernel32);
/* This call is only available from XP SP2 */
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, IsWow64Process, (HANDLE, PBOOL));

/* User32 dependencies */
DLL_DECLARE_HANDLE(User32);
DLL_DECLARE_FUNC_PREFIXED(WINAPI, BOOL, p, GetMessageA, (LPMSG, HWND, UINT, UINT));
@@ -287,12 +281,6 @@ void windows_force_sync_completion(OVERLAPPED *overlapped, ULONG size)

static BOOL windows_init_dlls(void)
{
DLL_GET_HANDLE(Kernel32);
DLL_LOAD_FUNC_PREFIXED(Kernel32, p, IsWow64Process, FALSE);
pCancelIoEx = (BOOL (WINAPI *)(HANDLE, LPOVERLAPPED))
GetProcAddress(DLL_HANDLE_NAME(Kernel32), "CancelIoEx");
usbi_dbg("Will use CancelIo%s for I/O cancellation", pCancelIoEx ? "Ex" : "");

DLL_GET_HANDLE(User32);
DLL_LOAD_FUNC_PREFIXED(User32, p, GetMessageA, TRUE);
DLL_LOAD_FUNC_PREFIXED(User32, p, PeekMessageA, TRUE);
@@ -303,7 +291,6 @@ static BOOL windows_init_dlls(void)

static void windows_exit_dlls(void)
{
DLL_FREE_HANDLE(Kernel32);
DLL_FREE_HANDLE(User32);
}

@@ -394,8 +381,7 @@ static BOOL is_x64(void)

// Detect if we're running a 32 or 64 bit system
if (sizeof(uintptr_t) < 8) {
if (pIsWow64Process != NULL)
pIsWow64Process(GetCurrentProcess(), &ret);
IsWow64Process(GetCurrentProcess(), &ret);
} else {
ret = TRUE;
}
@@ -134,9 +134,6 @@ enum windows_version {

extern enum windows_version windows_version;

/* This call is only available from Vista */
extern BOOL (WINAPI *pCancelIoEx)(HANDLE, LPOVERLAPPED);

#include <pshpack1.h>

typedef struct USB_DEVICE_DESCRIPTOR {
@@ -728,20 +728,12 @@ static int usbdk_abort_transfers(struct usbi_transfer *itransfer)
struct usbdk_transfer_priv *transfer_priv = _usbdk_transfer_priv(itransfer);
struct winfd *pollable_fd = &transfer_priv->pollable_fd;

if (pCancelIoEx != NULL) {
// Use CancelIoEx if available to cancel just a single transfer
if (!pCancelIoEx(priv->system_handle, pollable_fd->overlapped)) {
usbi_err(ctx, "CancelIoEx failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_DEVICE;
}
} else {
if (!usbdk_helper.AbortPipe(priv->redirector_handle, transfer->endpoint)) {
usbi_err(ctx, "AbortPipe failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NO_DEVICE;
}
}
// Use CancelIoEx to cancel just a single transfer
if (CancelIoEx(priv->system_handle, pollable_fd->overlapped))
return LIBUSB_SUCCESS;

return LIBUSB_SUCCESS;
usbi_warn(ctx, "CancelIoEx failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NOT_FOUND;
}

static int usbdk_cancel_transfer(struct usbi_transfer *itransfer)
@@ -2100,8 +2100,8 @@ static int winusbx_init(struct libusb_context *ctx)

if (WinUSBX[i].Initialize != NULL) {
WinUSBX[i].initialized = true;
// Assume driver supports CancelIoEx() if it is available
WinUSBX[i].CancelIoEx_supported = (pCancelIoEx != NULL);
// Assume driver supports CancelIoEx()
WinUSBX[i].CancelIoEx_supported = true;
usbi_dbg("initalized sub API %s", winusbx_driver_names[i]);
} else {
usbi_warn(ctx, "Failed to initalize sub API %s", winusbx_driver_names[i]);
@@ -2926,7 +2926,7 @@ static int winusbx_abort_transfers(int sub_api, struct usbi_transfer *itransfer)
if (WinUSBX[sub_api].CancelIoEx_supported) {
// Try to use CancelIoEx if available to cancel just a single transfer
handle = handle_priv->interface_handle[current_interface].dev_handle;
if (pCancelIoEx(handle, transfer_priv->pollable_fd.overlapped))
if (CancelIoEx(handle, transfer_priv->pollable_fd.overlapped))
return LIBUSB_SUCCESS;
else if (GetLastError() == ERROR_NOT_FOUND)
return LIBUSB_ERROR_NOT_FOUND;
@@ -3978,16 +3978,11 @@ static int hid_abort_transfers(int sub_api, struct usbi_transfer *itransfer)

hid_handle = handle_priv->interface_handle[current_interface].api_handle;

if (pCancelIoEx != NULL) {
// Use CancelIoEx if available to cancel just a single transfer
if (pCancelIoEx(hid_handle, transfer_priv->pollable_fd.overlapped))
// Use CancelIoEx to cancel just a single transfer
if (CancelIoEx(hid_handle, transfer_priv->pollable_fd.overlapped))
return LIBUSB_SUCCESS;
} else {
if (CancelIo(hid_handle))
return LIBUSB_SUCCESS;
}

usbi_warn(ctx, "cancel failed: %s", windows_error_str(0));
usbi_warn(ctx, "CancelIoEx failed: %s", windows_error_str(0));
return LIBUSB_ERROR_NOT_FOUND;
}

@@ -1 +1 @@
#define LIBUSB_NANO 11432
#define LIBUSB_NANO 11433
@@ -46,7 +46,7 @@
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WINVER=0x0501;_WIN32_WINNT=0x0501;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level4</WarningLevel>
</ClCompile>
<ClCompile Condition="'$(Configuration)'=='Debug'">
@@ -47,7 +47,7 @@
<ClCompile>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WINVER=0x0501;_WIN32_WINNT=0x0501;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level4</WarningLevel>
</ClCompile>
<ClCompile Condition="'$(Configuration)'=='Debug'">
@@ -66,7 +66,7 @@
<ClCompile>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WINVER=0x0501;_WIN32_WINNT=0x0501;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level4</WarningLevel>
</ClCompile>
<ClCompile Condition="'$(Configuration)'=='Debug'">
@@ -66,7 +66,7 @@
<ClCompile>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WINVER=0x0501;_WIN32_WINNT=0x0501;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<WarningLevel>Level4</WarningLevel>
</ClCompile>
<ClCompile Condition="'$(Configuration)'=='Debug'">
@@ -46,7 +46,7 @@
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WINVER=0x0501;_WIN32_WINNT=0x0501;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level4</WarningLevel>
</ClCompile>
@@ -47,7 +47,7 @@
<ClCompile>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WINVER=0x0501;_WIN32_WINNT=0x0501;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level4</WarningLevel>
</ClCompile>
@@ -66,7 +66,7 @@
<ClCompile>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WINVER=0x0501;_WIN32_WINNT=0x0501;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level4</WarningLevel>
</ClCompile>
@@ -66,7 +66,7 @@
<ClCompile>
<AdditionalOptions>/utf-8 %(AdditionalOptions)</AdditionalOptions>
<AdditionalIncludeDirectories>.;..\libusb;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WINVER=0x0501;_WIN32_WINNT=0x0501;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WIN32_WINNT=_WIN32_WINNT_VISTA;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName>
<WarningLevel>Level4</WarningLevel>
</ClCompile>

0 comments on commit 96e0af7

Please sign in to comment.
You can’t perform that action at this time.