Skip to content

Commit

Permalink
windows: hotplug implementation: use PDEV_BROADCAST_DEVICEINTERFACE->…
Browse files Browse the repository at this point in the history
…dbcc_name

for finding corresponding device in current context list and triggering LEFT
or ARRIVED event.
(No longer set LEFT / ARRIVED status during re-enumeration.)
  • Loading branch information
sonatique committed Jun 17, 2024
1 parent 2454f1a commit 127c1de
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 51 deletions.
18 changes: 0 additions & 18 deletions libusb/os/windows_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,29 +232,12 @@ 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, added when updating device list
* using system enumeration in response to low-level hotplug events */
enum hotplug_status {
/* device is still in system enumeration as it was in previous enumeration.
* There is no need to take any action */
UNCHANGED,

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

/* device is no longer present in system enumeration.
* A hotplug "device left" event shall be triggered and the device removed from the list */
LEFT
};

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 hotplug_status hotplug_status; /* updated while getting current device list */
};

struct winusb_device_priv {
Expand Down Expand Up @@ -286,7 +269,6 @@ 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 hotplug_status hotplug_status; /* updated while getting current device list */
};

struct usbdk_device_handle_priv {
Expand Down
77 changes: 51 additions & 26 deletions libusb/os/windows_hotplug.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,6 @@ int windows_stop_event_monitor(void)
static int windows_get_device_list(struct libusb_context *ctx)
{
// note: context device list is protected by active_contexts_lock
struct libusb_device *dev;
for_each_device(ctx, dev)
{
((struct winusb_device_priv *)usbi_get_device_priv(dev))->hotplug_status = LEFT;
}

return ((struct windows_context_priv *)usbi_get_context_priv(ctx))->backend->get_device_list(ctx);
}

Expand All @@ -100,7 +94,7 @@ void windows_initial_scan_devices(struct libusb_context *ctx)
usbi_mutex_static_unlock(&active_contexts_lock);
}

static void windows_refresh_device_list(struct libusb_context *ctx)
static void windows_refresh_device_list(struct libusb_context *ctx, const bool device_arrived, const char* device_name)
{
const int ret = windows_get_device_list(ctx);
if (ret != LIBUSB_SUCCESS)
Expand All @@ -115,42 +109,38 @@ static void windows_refresh_device_list(struct libusb_context *ctx)
for_each_device_safe(ctx, dev, next_dev)
{
priv = usbi_get_device_priv(dev);
if (priv->hotplug_status != LEFT)

if(_stricmp(priv->path, device_name) != 0)
{
continue;
}

if (priv->initialized)
if(device_arrived)
{
usbi_disconnect_device(dev);
usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED);
}
else
{
usbi_detach_device(dev);
}
}

for_each_device(ctx, dev)
{
priv = usbi_get_device_priv(dev);

if (priv->hotplug_status != ARRIVED)
{
continue;
if (priv->initialized)
{
usbi_disconnect_device(dev);
}
else
{
usbi_detach_device(dev);
}
}

usbi_hotplug_notification(ctx, dev, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED);
}
}

static void windows_refresh_device_list_for_all_ctx(void)
static void windows_refresh_device_list_for_all_ctx(const bool device_arrived, const char* device_name)
{
usbi_mutex_static_lock(&active_contexts_lock);

struct libusb_context *ctx;
for_each_context(ctx)
{
windows_refresh_device_list(ctx);
windows_refresh_device_list(ctx, device_arrived, device_name);
}

usbi_mutex_static_unlock(&active_contexts_lock);
Expand Down Expand Up @@ -281,7 +271,42 @@ static LRESULT CALLBACK windows_proc_callback(
case DBT_DEVICEREMOVECOMPLETE:
if (((PDEV_BROADCAST_HDR)lParam)->dbch_devicetype == DBT_DEVTYP_DEVICEINTERFACE)
{
windows_refresh_device_list_for_all_ctx();
#ifdef UNICODE
char* device_name = NULL;
const WCHAR* w_dbcc_name = ((PDEV_BROADCAST_DEVICEINTERFACE)lParam)->dbcc_name;

const int len = WideCharToMultiByte(CP_UTF8, 0, w_dbcc_name, -1, NULL, 0, NULL, NULL);
if (len == 0)
{
log_error("Conversion length calculation failed for ((PDEV_BROADCAST_DEVICEINTERFACE)lParam)->dbcc_name conversion from wchar to char");
}
else
{
device_name = (char *)malloc(len);
if (device_name == NULL)
{
log_error("Memory allocation failed for ((PDEV_BROADCAST_DEVICEINTERFACE)lParam)->dbcc_name conversion from wchar to char");
}
else
{
const int result = WideCharToMultiByte(CP_UTF8, 0, w_dbcc_name, -1, device_name, len, NULL, NULL);
if (result == 0)
{
log_error("Conversion failed for ((PDEV_BROADCAST_DEVICEINTERFACE)lParam)->dbcc_name conversion from wchar to char");
free(device_name);
device_name = NULL;
}
}
}
#else
const char* device_name = ((PDEV_BROADCAST_DEVICEINTERFACE)lParam)->dbcc_name;
#endif

windows_refresh_device_list_for_all_ctx(wParam == DBT_DEVICEARRIVAL ? true : false, device_name);

#ifdef UNICODE
free(device_name);
#endif
return TRUE;
}
break;
Expand Down
5 changes: 0 additions & 5 deletions libusb/os/windows_usbdk.c
Original file line number Diff line number Diff line change
Expand Up @@ -335,17 +335,12 @@ static int usbdk_get_device_list(struct libusb_context *ctx)
continue;
}

((struct winusb_device_priv *)usbi_get_device_priv(dev))->hotplug_status = ARRIVED;

usbdk_device_init(dev, &devices[i]);
if (usbdk_device_priv_init(ctx, dev, &devices[i]) != LIBUSB_SUCCESS) {
libusb_unref_device(dev);
continue;
}
}
else {
((struct winusb_device_priv *)usbi_get_device_priv(dev))->hotplug_status = UNCHANGED;
}
}

usbdk_helper.ReleaseDevicesList(devices);
Expand Down
2 changes: 0 additions & 2 deletions libusb/os/windows_winusb.c
Original file line number Diff line number Diff line change
Expand Up @@ -1860,7 +1860,6 @@ static int winusb_get_device_list(struct libusb_context *ctx)
usbi_attach_device(dev);

priv = winusb_device_priv_init(dev);
priv->hotplug_status = ARRIVED;
priv->dev_id = _strdup(dev_id);
priv->class_guid = dev_info_data.ClassGuid;
if (priv->dev_id == NULL) {
Expand Down Expand Up @@ -1957,7 +1956,6 @@ static int winusb_get_device_list(struct libusb_context *ctx)
if (priv->initialized) {
libusb_unref_device(parent_dev);
r = LIBUSB_SUCCESS;
priv->hotplug_status = UNCHANGED;
}
else {
if (!get_dev_port_number(*dev_info, &dev_info_data, &port_nr))
Expand Down

0 comments on commit 127c1de

Please sign in to comment.