From 127c1dee2b419c18cdbe7f2c1ef939742be9b8a1 Mon Sep 17 00:00:00 2001 From: Sylvain Fasel Date: Tue, 18 Jun 2024 00:34:27 +0800 Subject: [PATCH] windows: hotplug implementation: use PDEV_BROADCAST_DEVICEINTERFACE->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.) --- libusb/os/windows_common.h | 18 --------- libusb/os/windows_hotplug.c | 77 ++++++++++++++++++++++++------------- libusb/os/windows_usbdk.c | 5 --- libusb/os/windows_winusb.c | 2 - 4 files changed, 51 insertions(+), 51 deletions(-) diff --git a/libusb/os/windows_common.h b/libusb/os/windows_common.h index cf297c3b1..0afc9dc9b 100644 --- a/libusb/os/windows_common.h +++ b/libusb/os/windows_common.h @@ -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 { @@ -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 { diff --git a/libusb/os/windows_hotplug.c b/libusb/os/windows_hotplug.c index c147dc65f..419296456 100644 --- a/libusb/os/windows_hotplug.c +++ b/libusb/os/windows_hotplug.c @@ -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); } @@ -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) @@ -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); @@ -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; diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c index f85fe532d..49f88ea1f 100644 --- a/libusb/os/windows_usbdk.c +++ b/libusb/os/windows_usbdk.c @@ -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); diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c index e9b24e406..deb551beb 100644 --- a/libusb/os/windows_winusb.c +++ b/libusb/os/windows_winusb.c @@ -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) { @@ -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))