Skip to content

Commit

Permalink
windows: hotplug implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
sonatique committed Feb 4, 2024
1 parent e8a3b16 commit 88583d5
Show file tree
Hide file tree
Showing 11 changed files with 393 additions and 44 deletions.
3 changes: 2 additions & 1 deletion libusb/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ OS_SUNOS_SRC = os/sunos_usb.h os/sunos_usb.c
OS_WINDOWS_SRC = libusb-1.0.def libusb-1.0.rc \
os/windows_common.h os/windows_common.c \
os/windows_usbdk.h os/windows_usbdk.c \
os/windows_winusb.h os/windows_winusb.c
os/windows_winusb.h os/windows_winusb.c \
os/windows_hotplug.h os/windows_hotplug.c

if OS_DARWIN
OS_SRC = $(OS_DARWIN_SRC)
Expand Down
22 changes: 15 additions & 7 deletions libusb/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -728,20 +728,24 @@ struct libusb_device *usbi_alloc_device(struct libusb_context *ctx,
return dev;
}

void usbi_connect_device(struct libusb_device *dev)
void usbi_attach_device(struct libusb_device *dev)
{
struct libusb_context *ctx = DEVICE_CTX(dev);

usbi_atomic_store(&dev->attached, 1);

usbi_mutex_lock(&dev->ctx->usb_devs_lock);
list_add(&dev->list, &dev->ctx->usb_devs);
usbi_mutex_unlock(&dev->ctx->usb_devs_lock);
usbi_mutex_lock(&ctx->usb_devs_lock);
list_add(&dev->list, &ctx->usb_devs);
usbi_mutex_unlock(&ctx->usb_devs_lock);
}

usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED);
void usbi_connect_device(struct libusb_device *dev)
{
usbi_attach_device(dev);
usbi_hotplug_notification(DEVICE_CTX(dev), dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED);
}

void usbi_disconnect_device(struct libusb_device *dev)
void usbi_detach_device(struct libusb_device *dev)
{
struct libusb_context *ctx = DEVICE_CTX(dev);

Expand All @@ -750,8 +754,12 @@ void usbi_disconnect_device(struct libusb_device *dev)
usbi_mutex_lock(&ctx->usb_devs_lock);
list_del(&dev->list);
usbi_mutex_unlock(&ctx->usb_devs_lock);
}

usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT);
void usbi_disconnect_device(struct libusb_device *dev)
{
usbi_detach_device(dev);
usbi_hotplug_notification(DEVICE_CTX(dev), dev, LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT);
}

/* Perform some final sanity checks on a newly discovered device. If this
Expand Down
3 changes: 3 additions & 0 deletions libusb/libusbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -809,6 +809,9 @@ int usbi_handle_transfer_completion(struct usbi_transfer *itransfer,
int usbi_handle_transfer_cancellation(struct usbi_transfer *itransfer);
void usbi_signal_transfer_completion(struct usbi_transfer *itransfer);

void usbi_attach_device(struct libusb_device *dev);
void usbi_detach_device(struct libusb_device *dev);

void usbi_connect_device(struct libusb_device *dev);
void usbi_disconnect_device(struct libusb_device *dev);

Expand Down
24 changes: 17 additions & 7 deletions libusb/os/windows_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@

#include "libusbi.h"
#include "windows_common.h"
#include "windows_hotplug.h"

#define EPOCH_TIME UINT64_C(116444736000000000) // 1970.01.01 00:00:000 in MS Filetime

Expand Down Expand Up @@ -565,6 +566,20 @@ static int windows_init(struct libusb_context *ctx)

r = LIBUSB_SUCCESS;

if (init_count == 1) {
r = windows_start_event_monitor();
}
if (r != LIBUSB_SUCCESS) {
usbi_err(ctx, "error starting hotplug event monitor");

if (init_count == 1) {
windows_stop_event_monitor();
}
goto init_exit;
}

windows_initial_scan_devices(ctx);

init_exit: // Holds semaphore here
if ((init_count == 1) && (r != LIBUSB_SUCCESS)) { // First init failed?
if (usbdk_available) {
Expand Down Expand Up @@ -596,6 +611,7 @@ static void windows_exit(struct libusb_context *ctx)

// Only works if exits and inits are balanced exactly
if (--init_count == 0) { // Last exit
windows_stop_event_monitor();
if (usbdk_available) {
usbdk_backend.exit(ctx);
usbdk_available = false;
Expand Down Expand Up @@ -624,12 +640,6 @@ static int windows_set_option(struct libusb_context *ctx, enum libusb_option opt
return LIBUSB_ERROR_NOT_SUPPORTED;
}

static int windows_get_device_list(struct libusb_context *ctx, struct discovered_devs **discdevs)
{
struct windows_context_priv *priv = usbi_get_context_priv(ctx);
return priv->backend->get_device_list(ctx, discdevs);
}

static int windows_open(struct libusb_device_handle *dev_handle)
{
struct windows_context_priv *priv = usbi_get_context_priv(HANDLE_CTX(dev_handle));
Expand Down Expand Up @@ -888,7 +898,7 @@ const struct usbi_os_backend usbi_backend = {
windows_init,
windows_exit,
windows_set_option,
windows_get_device_list,
NULL, /* get_device_list */
NULL, /* hotplug_poll */
NULL, /* wrap_sys_device */
windows_open,
Expand Down
21 changes: 19 additions & 2 deletions libusb/os/windows_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,29 @@ typedef struct USB_DK_TRANSFER_REQUEST {
USB_DK_TRANSFER_RESULT Result;
} USB_DK_TRANSFER_REQUEST, *PUSB_DK_TRANSFER_REQUEST;

/* track devices that are removed, kept unchanged, or added when updating device list
* using system enumeration, in response to low-level hotplug related events */
enum enumeration_status {
/* device is no longer present in system enumeration.
* A hotplug "device left" event shall be triggered and the device removed from the list */
NO_LONGER_ENUMERATED,

/* device is still in system enumeration as it was in previous enumeration.
* There is no need to take any action */
STILL_ENUMERATED,

/* device is newly added to the list, meaning it just appeared in system enumeration.
* A hotplug "device arrived" event shall be triggered */
NEWLY_ENUMERATED
};

struct usbdk_device_priv {
USB_DK_DEVICE_ID ID;
PUSB_CONFIGURATION_DESCRIPTOR *config_descriptors;
HANDLE redirector_handle;
HANDLE system_handle;
uint8_t active_configuration;
enum enumeration_status discovery_status; /* updated while getting current device list */
};

struct winusb_device_priv {
Expand Down Expand Up @@ -269,6 +286,7 @@ struct winusb_device_priv {
struct hid_device_priv *hid;
PUSB_CONFIGURATION_DESCRIPTOR *config_descriptor; // list of pointers to the cached config descriptors
GUID class_guid; // checked for change during re-enumeration
enum enumeration_status discovery_status;
};

struct usbdk_device_handle_priv {
Expand Down Expand Up @@ -318,8 +336,7 @@ struct winusb_transfer_priv {
struct windows_backend {
int (*init)(struct libusb_context *ctx);
void (*exit)(struct libusb_context *ctx);
int (*get_device_list)(struct libusb_context *ctx,
struct discovered_devs **discdevs);
int (*get_device_list)(struct libusb_context *ctx);
int (*open)(struct libusb_device_handle *dev_handle);
void (*close)(struct libusb_device_handle *dev_handle);
int (*get_active_config_descriptor)(struct libusb_device *device,
Expand Down
Loading

0 comments on commit 88583d5

Please sign in to comment.