Fix #5910: USB hotplug added device wrong
authorArmin Novak <armin.novak@thincast.com>
Wed, 26 Feb 2020 11:24:25 +0000 (12:24 +0100)
committerakallabeth <akallabeth@users.noreply.github.com>
Mon, 2 Mar 2020 10:40:05 +0000 (11:40 +0100)
When a USB device was added via hotplug add_device was called
with wrong arguments.

channels/urbdrc/client/data_transfer.c
channels/urbdrc/client/libusb/libusb_udevice.c
channels/urbdrc/client/libusb/libusb_udevice.h
channels/urbdrc/client/libusb/libusb_udevman.c
channels/urbdrc/client/searchman.c
channels/urbdrc/client/searchman.h
channels/urbdrc/client/urbdrc_main.c
channels/urbdrc/client/urbdrc_main.h

index 1e71edd..25918b8 100644 (file)
@@ -348,7 +348,6 @@ static UINT urbdrc_process_query_device_text(IUDEVICE* pdev, URBDRC_CHANNEL_CALL
 
        if (!pdev || !callback || !s || !udevman)
                return ERROR_INVALID_PARAMETER;
-
        if (Stream_GetRemainingLength(s) < 8)
                return ERROR_INVALID_DATA;
 
@@ -1816,5 +1815,10 @@ UINT urbdrc_process_udev_data_transfer(URBDRC_CHANNEL_CALLBACK* callback, URBDRC
        }
 
 fail:
+       if (error)
+       {
+               WLog_WARN(TAG, "USB request failed with %08" PRIx32, error);
+       }
+
        return error;
 }
index 0c53b30..0801c00 100644 (file)
@@ -81,6 +81,51 @@ struct _ASYNC_TRANSFER_USER_DATA
 #endif
 };
 
+const char* usb_interface_class_to_string(uint8_t class)
+{
+       switch (class)
+       {
+               case LIBUSB_CLASS_PER_INTERFACE:
+                       return "LIBUSB_CLASS_PER_INTERFACE";
+               case LIBUSB_CLASS_AUDIO:
+                       return "LIBUSB_CLASS_AUDIO";
+               case LIBUSB_CLASS_COMM:
+                       return "LIBUSB_CLASS_COMM";
+               case LIBUSB_CLASS_HID:
+                       return "LIBUSB_CLASS_HID";
+               case LIBUSB_CLASS_PHYSICAL:
+                       return "LIBUSB_CLASS_PHYSICAL";
+               case LIBUSB_CLASS_PRINTER:
+                       return "LIBUSB_CLASS_PRINTER";
+               case LIBUSB_CLASS_IMAGE:
+                       return "LIBUSB_CLASS_IMAGE";
+               case LIBUSB_CLASS_MASS_STORAGE:
+                       return "LIBUSB_CLASS_MASS_STORAGE";
+               case LIBUSB_CLASS_HUB:
+                       return "LIBUSB_CLASS_HUB";
+               case LIBUSB_CLASS_DATA:
+                       return "LIBUSB_CLASS_DATA";
+               case LIBUSB_CLASS_SMART_CARD:
+                       return "LIBUSB_CLASS_SMART_CARD";
+               case LIBUSB_CLASS_CONTENT_SECURITY:
+                       return "LIBUSB_CLASS_CONTENT_SECURITY";
+               case LIBUSB_CLASS_VIDEO:
+                       return "LIBUSB_CLASS_VIDEO";
+               case LIBUSB_CLASS_PERSONAL_HEALTHCARE:
+                       return "LIBUSB_CLASS_PERSONAL_HEALTHCARE";
+               case LIBUSB_CLASS_DIAGNOSTIC_DEVICE:
+                       return "LIBUSB_CLASS_DIAGNOSTIC_DEVICE";
+               case LIBUSB_CLASS_WIRELESS:
+                       return "LIBUSB_CLASS_WIRELESS";
+               case LIBUSB_CLASS_APPLICATION:
+                       return "LIBUSB_CLASS_APPLICATION";
+               case LIBUSB_CLASS_VENDOR_SPEC:
+                       return "LIBUSB_CLASS_VENDOR_SPEC";
+               default:
+                       return "UNKNOWN_DEVICE_CLASS";
+       }
+}
+
 static ASYNC_TRANSFER_USER_DATA* async_transfer_user_data_new(IUDEVICE* idev, UINT32 MessageId,
                                                               size_t offset, size_t BufferSize,
                                                               size_t packetSize, BOOL NoAck,
@@ -375,21 +420,28 @@ static int func_claim_all_interface(URBDRC_PLUGIN* urbdrc, LIBUSB_DEVICE_HANDLE*
        return 0;
 }
 
-static LIBUSB_DEVICE* udev_get_libusb_dev(int bus_number, int dev_number)
+static LIBUSB_DEVICE* udev_get_libusb_dev(libusb_context* context, uint8_t bus_number,
+                                          uint8_t dev_number)
 {
        ssize_t i, total_device;
        LIBUSB_DEVICE** libusb_list;
-       total_device = libusb_get_device_list(NULL, &libusb_list);
+       LIBUSB_DEVICE* device = NULL;
+       total_device = libusb_get_device_list(context, &libusb_list);
 
        for (i = 0; i < total_device; i++)
        {
-               if ((bus_number == libusb_get_bus_number(libusb_list[i])) &&
-                   (dev_number == libusb_get_device_address(libusb_list[i])))
-                       return libusb_list[i];
+               uint8_t cbus = libusb_get_bus_number(libusb_list[i]);
+               uint8_t caddr = libusb_get_device_address(libusb_list[i]);
+
+               if ((bus_number == cbus) && (dev_number == caddr))
+               {
+                       device = libusb_list[i];
+                       break;
+               }
        }
 
        libusb_free_device_list(libusb_list, 1);
-       return NULL;
+       return device;
 }
 
 static LIBUSB_DEVICE_DESCRIPTOR* udev_new_descript(URBDRC_PLUGIN* urbdrc, LIBUSB_DEVICE* libusb_dev)
@@ -901,12 +953,14 @@ static BOOL libusb_udev_detach_kernel_driver(IUDEVICE* idev)
                for (i = 0; i < pdev->LibusbConfig->bNumInterfaces; i++)
                {
                        err = libusb_kernel_driver_active(pdev->libusb_handle, i);
-                       WLog_Print(urbdrc->log, WLOG_DEBUG, "libusb_kernel_driver_active = %d", err);
+                       WLog_Print(urbdrc->log, WLOG_DEBUG, "libusb_kernel_driver_active = %s [%d]",
+                                  libusb_error_name(err), err);
 
                        if (err)
                        {
                                err = libusb_detach_kernel_driver(pdev->libusb_handle, i);
-                               WLog_Print(urbdrc->log, WLOG_DEBUG, "libusb_detach_kernel_driver = %d", err);
+                               WLog_Print(urbdrc->log, WLOG_DEBUG, "libusb_detach_kernel_driver = %s [%d]",
+                                          libusb_error_name(err), err);
                        }
                }
 
@@ -981,23 +1035,30 @@ static int libusb_udev_is_already_send(IUDEVICE* idev)
 static void libusb_udev_channel_closed(IUDEVICE* idev)
 {
        UDEVICE* pdev = (UDEVICE*)idev;
-       const UINT16 idVendor = (UINT16)idev->query_device_descriptor(idev, ID_VENDOR);
-       const UINT16 idProduct = (UINT16)idev->query_device_descriptor(idev, ID_PRODUCT);
-       const uint8_t busNr = idev->get_bus_number(idev);
-       const uint8_t devNr = idev->get_dev_number(idev);
-       IWTSVirtualChannel* channel =
-           pdev->channelManager->FindChannelById(pdev->channelManager, pdev->channelID);
-       pdev->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
-
-       if (channel)
+       if (pdev)
        {
-               URBDRC_PLUGIN* urbdrc = pdev->urbdrc;
-               USB_SEARCHMAN* searchman = urbdrc->searchman;
+               const UINT16 idVendor = (UINT16)idev->query_device_descriptor(idev, ID_VENDOR);
+               const UINT16 idProduct = (UINT16)idev->query_device_descriptor(idev, ID_PRODUCT);
+               const uint8_t busNr = idev->get_bus_number(idev);
+               const uint8_t devNr = idev->get_dev_number(idev);
+               IWTSVirtualChannel* channel = NULL;
+
+               if (pdev->channelManager)
+                       channel = IFCALLRESULT(NULL, pdev->channelManager->FindChannelById,
+                                              pdev->channelManager, pdev->channelID);
 
-               /* Notify the server the device is no longer available. */
-               channel->Write(channel, 0, NULL, NULL);
-               urbdrc->udevman->unregister_udevice(urbdrc->udevman, busNr, devNr);
-               searchman->add(searchman, idVendor, idProduct);
+               pdev->status |= URBDRC_DEVICE_CHANNEL_CLOSED;
+
+               if (channel)
+               {
+                       URBDRC_PLUGIN* urbdrc = pdev->urbdrc;
+                       USB_SEARCHMAN* searchman = urbdrc->searchman;
+
+                       /* Notify the server the device is no longer available. */
+                       channel->Write(channel, 0, NULL, NULL);
+                       urbdrc->udevman->unregister_udevice(urbdrc->udevman, busNr, devNr);
+                       searchman->add(searchman, idVendor, idProduct);
+               }
        }
 }
 
@@ -1013,11 +1074,6 @@ static char* libusb_udev_get_path(IUDEVICE* idev)
        return pdev->path;
 }
 
-static BOOL libusb_udev_wait_for_detach(IUDEVICE* idev)
-{
-       return TRUE;
-}
-
 static int libusb_udev_query_device_port_status(IUDEVICE* idev, UINT32* UsbdStatus,
                                                 UINT32* BufferSize, BYTE* Buffer)
 {
@@ -1350,7 +1406,7 @@ static void udev_free(IUDEVICE* idev)
 
                if (rc != LIBUSB_SUCCESS)
                {
-                       WLog_Print(urbdrc->log, WLOG_ERROR, "libusb_reset_device: error %s [%d[",
+                       WLog_Print(urbdrc->log, WLOG_ERROR, "libusb_reset_device: error %s [%d]",
                                   libusb_error_name(rc), rc);
                }
        }
@@ -1404,27 +1460,27 @@ static void udev_load_interface(UDEVICE* pdev)
        pdev->iface.detach_kernel_driver = libusb_udev_detach_kernel_driver;
        pdev->iface.attach_kernel_driver = libusb_udev_attach_kernel_driver;
        pdev->iface.query_device_port_status = libusb_udev_query_device_port_status;
-       pdev->iface.wait_for_detach = libusb_udev_wait_for_detach;
        pdev->iface.free = udev_free;
 }
 
-static int udev_get_hub_handle(URBDRC_PLUGIN* urbdrc, UDEVICE* pdev, UINT16 bus_number,
-                               UINT16 dev_number)
+static int udev_get_hub_handle(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UDEVICE* pdev,
+                               UINT16 bus_number, UINT16 dev_number)
 {
        int error;
        ssize_t i, total_device;
        uint8_t port_numbers[16];
        LIBUSB_DEVICE** libusb_list;
-       total_device = libusb_get_device_list(NULL, &libusb_list);
+       total_device = libusb_get_device_list(ctx, &libusb_list);
        /* Look for device. */
        error = -1;
 
        for (i = 0; i < total_device; i++)
        {
                LIBUSB_DEVICE_HANDLE* handle;
+               uint8_t cbus = libusb_get_bus_number(libusb_list[i]);
+               uint8_t caddr = libusb_get_device_address(libusb_list[i]);
 
-               if ((bus_number != libusb_get_bus_number(libusb_list[i])) ||
-                   (dev_number != libusb_get_device_address(libusb_list[i])))
+               if ((bus_number != cbus) || (dev_number != caddr))
                        continue;
 
                error = libusb_open(libusb_list[i], &handle);
@@ -1465,10 +1521,10 @@ static int udev_get_hub_handle(URBDRC_PLUGIN* urbdrc, UDEVICE* pdev, UINT16 bus_
                for (i = 0; i < total_device; i++)
                {
                        LIBUSB_DEVICE_HANDLE* handle;
+                       uint8_t cbus = libusb_get_bus_number(libusb_list[i]);
+                       uint8_t caddr = libusb_get_device_address(libusb_list[i]);
 
-                       if ((bus_number != libusb_get_bus_number(libusb_list[i])) ||
-                           (1 !=
-                            libusb_get_device_address(libusb_list[i]))) /* Root hub allways first on bus. */
+                       if ((bus_number != cbus) || (1 != caddr)) /* Root hub allways first on bus. */
                                continue;
 
                        WLog_Print(urbdrc->log, WLOG_DEBUG, "  Open hub: %" PRIu16 "", bus_number);
@@ -1503,11 +1559,11 @@ static void request_free(void* value)
        async_transfer_user_data_free(user_data);
 }
 
-static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, LIBUSB_DEVICE* device, BYTE bus_number,
-                           BYTE dev_number)
+static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, libusb_context* context, LIBUSB_DEVICE* device,
+                           BYTE bus_number, BYTE dev_number)
 {
        UDEVICE* pdev;
-       int status;
+       int status = LIBUSB_ERROR_OTHER;
        LIBUSB_DEVICE_DESCRIPTOR* devDescriptor;
        LIBUSB_CONFIG_DESCRIPTOR* config_temp;
        LIBUSB_INTERFACE_DESCRIPTOR interface_temp;
@@ -1522,26 +1578,39 @@ static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, LIBUSB_DEVICE* device, BYTE bu
        if (device)
                pdev->libusb_dev = device;
        else
-               pdev->libusb_dev = udev_get_libusb_dev(bus_number, dev_number);
+               pdev->libusb_dev = udev_get_libusb_dev(context, bus_number, dev_number);
 
        if (pdev->libusb_dev == NULL)
                goto fail;
 
-       status = libusb_open(pdev->libusb_dev, &pdev->libusb_handle);
-
-       if (status < 0)
-       {
-               WLog_Print(urbdrc->log, WLOG_ERROR, "libusb_open error: %i - %s", status,
-                          libusb_error_name(status));
-               goto fail;
-       }
+       if (urbdrc->listener_callback)
+               udev_set_channelManager(&pdev->iface, urbdrc->listener_callback->channel_mgr);
 
        /* Get HUB handle */
-       status = udev_get_hub_handle(urbdrc, pdev, bus_number, dev_number);
+       status = udev_get_hub_handle(urbdrc, context, pdev, bus_number, dev_number);
 
        if (status < 0)
                pdev->hub_handle = NULL;
 
+       {
+               struct libusb_device_descriptor desc;
+               const uint8_t bus = libusb_get_bus_number(pdev->libusb_dev);
+               const uint8_t port = libusb_get_port_number(pdev->libusb_dev);
+               const uint8_t addr = libusb_get_device_address(pdev->libusb_dev);
+               libusb_get_device_descriptor(pdev->libusb_dev, &desc);
+
+               status = libusb_open(pdev->libusb_dev, &pdev->libusb_handle);
+
+               if (status != LIBUSB_SUCCESS)
+               {
+                       WLog_Print(
+                           urbdrc->log, WLOG_ERROR,
+                           "libusb_open error: %i - %s [b=0x%02X,p=0x%02X,a=0x%02X,VID=0x%04X,PID=0x%04X]",
+                           status, libusb_error_name(status), bus, port, addr, desc.idVendor, desc.idProduct);
+                       goto fail;
+               }
+       }
+
        pdev->devDescriptor = udev_new_descript(urbdrc, pdev->libusb_dev);
 
        if (!pdev->devDescriptor)
@@ -1560,19 +1629,20 @@ static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, LIBUSB_DEVICE* device, BYTE bu
        interface_temp = config_temp->interface[0].altsetting[0];
        WLog_Print(urbdrc->log, WLOG_DEBUG,
                   "Registered Device: Vid: 0x%04" PRIX16 " Pid: 0x%04" PRIX16 ""
-                  " InterfaceClass = 0x%02" PRIX8 "",
+                  " InterfaceClass = %s",
                   pdev->devDescriptor->idVendor, pdev->devDescriptor->idProduct,
-                  interface_temp.bInterfaceClass);
+                  usb_interface_class_to_string(interface_temp.bInterfaceClass));
        /* Check composite device */
        devDescriptor = pdev->devDescriptor;
 
        if ((devDescriptor->bNumConfigurations == 1) && (config_temp->bNumInterfaces > 1) &&
-           (devDescriptor->bDeviceClass == 0x0))
+           (devDescriptor->bDeviceClass == LIBUSB_CLASS_PER_INTERFACE))
        {
                pdev->isCompositeDevice = 1;
        }
-       else if ((devDescriptor->bDeviceClass == 0xef) && (devDescriptor->bDeviceSubClass == 0x02) &&
-                (devDescriptor->bDeviceProtocol == 0x01))
+       else if ((devDescriptor->bDeviceClass == LIBUSB_CLASS_APPLICATION) &&
+                (devDescriptor->bDeviceSubClass == LIBUSB_CLASS_COMM) &&
+                (devDescriptor->bDeviceProtocol == LIBUSB_CLASS_AUDIO))
        {
                pdev->isCompositeDevice = 1;
        }
@@ -1606,7 +1676,7 @@ fail:
        return NULL;
 }
 
-size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, UINT16 idVendor, UINT16 idProduct,
+size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UINT16 idVendor, UINT16 idProduct,
                       IUDEVICE*** devArray)
 {
        LIBUSB_DEVICE** libusb_list;
@@ -1626,7 +1696,7 @@ size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, UINT16 idVendor, UINT16 idProduct,
        if (!array)
                return 0;
 
-       total_device = libusb_get_device_list(NULL, &libusb_list);
+       total_device = libusb_get_device_list(ctx, &libusb_list);
 
        for (i = 0; i < total_device; i++)
        {
@@ -1636,7 +1706,7 @@ size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, UINT16 idVendor, UINT16 idProduct,
                {
                        bus_number = libusb_get_bus_number(libusb_list[i]);
                        dev_number = libusb_get_device_address(libusb_list[i]);
-                       array[num] = (PUDEVICE)udev_init(urbdrc, libusb_list[i], bus_number, dev_number);
+                       array[num] = (PUDEVICE)udev_init(urbdrc, ctx, libusb_list[i], bus_number, dev_number);
 
                        if (array[num] != NULL)
                                num++;
@@ -1650,8 +1720,9 @@ size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, UINT16 idVendor, UINT16 idProduct,
        return num;
 }
 
-IUDEVICE* udev_new_by_addr(URBDRC_PLUGIN* urbdrc, BYTE bus_number, BYTE dev_number)
+IUDEVICE* udev_new_by_addr(URBDRC_PLUGIN* urbdrc, libusb_context* context, BYTE bus_number,
+                           BYTE dev_number)
 {
        WLog_Print(urbdrc->log, WLOG_DEBUG, "bus:%d dev:%d", bus_number, dev_number);
-       return udev_init(urbdrc, NULL, bus_number, dev_number);
+       return udev_init(urbdrc, context, NULL, bus_number, dev_number);
 }
index 246f1e0..cf421d0 100644 (file)
@@ -69,8 +69,10 @@ struct _UDEVICE
 };
 typedef UDEVICE* PUDEVICE;
 
-size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, UINT16 idVendor, UINT16 idProduct,
+size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UINT16 idVendor, UINT16 idProduct,
                       IUDEVICE*** devArray);
-IUDEVICE* udev_new_by_addr(URBDRC_PLUGIN* urbdrc, BYTE bus_number, BYTE dev_number);
+IUDEVICE* udev_new_by_addr(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, BYTE bus_number,
+                           BYTE dev_number);
+const char* usb_interface_class_to_string(uint8_t class);
 
 #endif /* FREERDP_CHANNEL_URBDRC_CLIENT_LIBUSB_UDEVICE_H */
index d7a7d8d..40c39ae 100644 (file)
@@ -151,7 +151,7 @@ static size_t udevman_register_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE
 
        if (flag == UDEVMAN_FLAG_ADD_BY_ADDR)
        {
-               IUDEVICE* tdev = udev_new_by_addr(urbdrc, bus_number, dev_number);
+               IUDEVICE* tdev = udev_new_by_addr(urbdrc, udevman->context, bus_number, dev_number);
 
                if (tdev == NULL)
                        return 0;
@@ -180,7 +180,7 @@ static size_t udevman_register_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE
        {
                addnum = 0;
                /* register all device that match pid vid */
-               num = udev_new_by_id(urbdrc, idVendor, idProduct, &devArray);
+               num = udev_new_by_id(urbdrc, udevman->context, idVendor, idProduct, &devArray);
 
                for (i = 0; i < num; i++)
                {
@@ -435,14 +435,6 @@ static BOOL udevman_parse_device_pid_vid(const char* str, size_t maxLen, UINT16*
        return TRUE;
 }
 
-static int udevman_check_device_exist_by_id(IUDEVMAN* idevman, UINT16 idVendor, UINT16 idProduct)
-{
-       if (libusb_open_device_with_vid_pid(NULL, idVendor, idProduct))
-               return 1;
-
-       return 0;
-}
-
 static int udevman_is_auto_add(IUDEVMAN* idevman)
 {
        UDEVMAN* udevman = (UDEVMAN*)idevman;
@@ -520,27 +512,131 @@ static void udevman_free(IUDEVMAN* idevman)
        free(udevman);
 }
 
+static BOOL filter_by_class(uint8_t bDeviceClass, uint8_t bDeviceSubClass)
+{
+       switch (bDeviceClass)
+       {
+               case LIBUSB_CLASS_AUDIO:
+               case LIBUSB_CLASS_HID:
+               case LIBUSB_CLASS_MASS_STORAGE:
+               case LIBUSB_CLASS_HUB:
+               case LIBUSB_CLASS_SMART_CARD:
+                       return TRUE;
+               default:
+                       break;
+       }
+
+       switch (bDeviceSubClass)
+       {
+               default:
+                       break;
+       }
+
+       return FALSE;
+}
+
+static BOOL append(char* dst, size_t length, const char* src)
+{
+       size_t slen = strlen(src);
+       size_t dlen = strnlen(dst, length);
+       if (dlen + slen >= length)
+               return FALSE;
+       strcat(dst, src);
+       return TRUE;
+}
+
+static BOOL device_is_filtered(struct libusb_device* dev,
+                               const struct libusb_device_descriptor* desc,
+                               libusb_hotplug_event event)
+{
+       char buffer[8192] = { 0 };
+       char* what;
+       BOOL filtered = FALSE;
+       append(buffer, sizeof(buffer), usb_interface_class_to_string(desc->bDeviceClass));
+       if (filter_by_class(desc->bDeviceClass, desc->bDeviceSubClass))
+               filtered = TRUE;
+
+       switch (desc->bDeviceClass)
+       {
+               case LIBUSB_CLASS_PER_INTERFACE:
+               {
+                       struct libusb_config_descriptor* config = NULL;
+                       int rc = libusb_get_active_config_descriptor(dev, &config);
+                       if (rc == LIBUSB_SUCCESS)
+                       {
+                               uint8_t x;
+
+                               for (x = 0; x < config->bNumInterfaces; x++)
+                               {
+                                       uint8_t y;
+                                       const struct libusb_interface* ifc = &config->interface[x];
+                                       for (y = 0; y < ifc->num_altsetting; y++)
+                                       {
+                                               const struct libusb_interface_descriptor* const alt = &ifc->altsetting[y];
+                                               if (filter_by_class(alt->bInterfaceClass, alt->bInterfaceSubClass))
+                                                       filtered = TRUE;
+
+                                               append(buffer, sizeof(buffer), "|");
+                                               append(buffer, sizeof(buffer),
+                                                      usb_interface_class_to_string(alt->bInterfaceClass));
+                                       }
+                               }
+                       }
+                       libusb_free_config_descriptor(config);
+               }
+               break;
+               default:
+                       break;
+       }
+
+       if (filtered)
+               what = "Filtered";
+       else
+       {
+               switch (event)
+               {
+                       case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
+                               what = "Hotplug remove";
+                               break;
+                       case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
+                               what = "Hotplug add";
+                               break;
+                       default:
+                               what = "Hotplug unknown";
+                               break;
+               }
+       }
+
+       WLog_DBG(TAG, "%s device VID=0x%04X,PID=0x%04X class %s", what, desc->idVendor, desc->idProduct,
+                buffer);
+       return filtered;
+}
+
 static int hotplug_callback(struct libusb_context* ctx, struct libusb_device* dev,
                             libusb_hotplug_event event, void* user_data)
 {
-       int rc;
        struct libusb_device_descriptor desc;
        IUDEVMAN* idevman = (IUDEVMAN*)user_data;
        const uint8_t bus = libusb_get_bus_number(dev);
        const uint8_t addr = libusb_get_device_address(dev);
-       rc = libusb_get_device_descriptor(dev, &desc);
+       int rc = libusb_get_device_descriptor(dev, &desc);
+
+       WINPR_UNUSED(ctx);
 
        if (rc != LIBUSB_SUCCESS)
                return rc;
 
+       if (device_is_filtered(dev, &desc, event))
+               return 0;
+
        switch (event)
        {
                case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
-                       add_device(idevman, bus, addr, desc.iManufacturer, desc.iProduct);
+                       add_device(idevman, bus, addr, desc.idVendor, desc.idProduct);
                        break;
 
                case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
-                       del_device(idevman, bus, addr, desc.iManufacturer, desc.iProduct);
+                       del_device(idevman, bus, addr, desc.idVendor, desc.idProduct);
                        break;
 
                default:
@@ -573,7 +669,6 @@ static void udevman_load_interface(UDEVMAN* udevman)
        udevman->iface.unregister_udevice = udevman_unregister_udevice;
        udevman->iface.get_udevice_by_UsbDevice = udevman_get_udevice_by_UsbDevice;
        /* Extension */
-       udevman->iface.check_device_exist_by_id = udevman_check_device_exist_by_id;
        udevman->iface.isAutoAdd = udevman_is_auto_add;
        /* Basic state */
        BASIC_STATE_FUNC_REGISTER(defUsbDevice, udevman);
index 6d109f2..39bb5ee 100644 (file)
@@ -33,22 +33,42 @@ static void searchman_rewind(USB_SEARCHMAN* searchman)
        searchman->idev = searchman->head;
 }
 
-static int searchman_has_next(USB_SEARCHMAN* searchman)
-{
-       if (searchman->idev == NULL)
-               return 0;
-       else
-               return 1;
-}
-
 static USB_SEARCHDEV* searchman_get_next(USB_SEARCHMAN* searchman)
 {
        USB_SEARCHDEV* search;
+       if (!searchman)
+               return NULL;
+
        search = searchman->idev;
+       if (!search)
+               return NULL;
+
        searchman->idev = (USB_SEARCHDEV*)searchman->idev->next;
        return search;
 }
 
+static USB_SEARCHDEV* searchman_get_by_vid_pid(USB_SEARCHMAN* searchman, UINT16 idVendor,
+                                               UINT16 idProduct)
+{
+       USB_SEARCHDEV* dev;
+       if (!searchman)
+               return NULL;
+
+       searchman->rewind(searchman);
+
+       while ((dev = searchman->get_next(searchman)) != NULL)
+       {
+               if ((dev->idVendor == idVendor) && (dev->idProduct == idProduct))
+               {
+                       WLog_VRB(TAG, "Searchman Find Device: %04" PRIx16 ":%04" PRIx16 "", dev->idVendor,
+                                dev->idProduct);
+                       return dev;
+               }
+       }
+
+       return NULL;
+}
+
 static BOOL searchman_list_add(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT16 idProduct)
 {
        USB_SEARCHDEV* search;
@@ -84,11 +104,9 @@ static int searchman_list_remove(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT
        USB_SEARCHDEV* point;
        searchman_rewind(searchman);
 
-       while (searchman_has_next(searchman) != 0)
+       while ((point = searchman_get_next(searchman)) != NULL)
        {
-               point = searchman_get_next(searchman);
-
-               if (point->idVendor == idVendor && point->idProduct == idProduct)
+               if ((point->idVendor == idVendor) && (point->idProduct == idProduct))
                {
                        /* set previous device to point to next device */
                        search = point;
@@ -143,9 +161,8 @@ static void searchman_list_show(USB_SEARCHMAN* self)
        WLog_Print(urbdrc->log, WLOG_DEBUG, "=========== Usb Search List =========");
        self->rewind(self);
 
-       while (self->has_next(self))
+       while ((usb = self->get_next(self)) != NULL)
        {
-               usb = self->get_next(self);
                WLog_Print(urbdrc->log, WLOG_DEBUG, "  USB %d: ", num++);
                WLog_Print(urbdrc->log, WLOG_DEBUG, "   idVendor: 0x%04" PRIX16 "", usb->idVendor);
                WLog_Print(urbdrc->log, WLOG_DEBUG, "   idProduct: 0x%04" PRIX16 "", usb->idProduct);
@@ -183,8 +200,8 @@ USB_SEARCHMAN* searchman_new(void* urbdrc, UINT32 UsbDevice)
        searchman->remove = searchman_list_remove;
        searchman->rewind = searchman_rewind;
        searchman->get_next = searchman_get_next;
-       searchman->has_next = searchman_has_next;
        searchman->show = searchman_list_show;
+       searchman->get_next_by_vid_pid = searchman_get_by_vid_pid;
        searchman->free = searchman_free;
        return searchman;
 }
index 4e29f0d..4f1d316 100644 (file)
@@ -55,10 +55,11 @@ struct _USB_SEARCHMAN
        BOOL (*add)(USB_SEARCHMAN* seachman, UINT16 idVendor, UINT16 idProduct);
        /* remove a usb device from list */
        int (*remove)(USB_SEARCHMAN* searchman, UINT16 idVendor, UINT16 idProduct);
-       /* check list has next device*/
-       int (*has_next)(USB_SEARCHMAN* seachman);
        /* get the device from list*/
        USB_SEARCHDEV* (*get_next)(USB_SEARCHMAN* seachman);
+       /* get the device by vendor and product */
+       USB_SEARCHDEV* (*get_next_by_vid_pid)(USB_SEARCHMAN* seachman, UINT16 idVendor,
+                                             UINT16 idProduct);
        /* free! */
        void (*free)(USB_SEARCHMAN* searchman);
 };
index 4bc3cfb..dfdf1ce 100644 (file)
@@ -825,42 +825,27 @@ BOOL add_device(IUDEVMAN* idevman, BYTE busnum, BYTE devnum, UINT16 idVendor, UI
        if (!searchman)
                return FALSE;
 
-       searchman->rewind(searchman);
+       sdev = searchman->get_next_by_vid_pid(searchman, idVendor, idProduct);
 
-       while (searchman->has_next(searchman))
-       {
-               USB_SEARCHDEV* dev = searchman->get_next(searchman);
-
-               if (dev->idVendor == idVendor && dev->idProduct == idProduct)
-               {
-                       WLog_Print(urbdrc->log, WLOG_TRACE,
-                                  "Searchman Find Device: %04" PRIx16 ":%04" PRIx16 "", dev->idVendor,
-                                  dev->idProduct);
-                       found = TRUE;
-                       sdev = dev;
-                       break;
-               }
-       }
-
-       if (!found && idevman->isAutoAdd(idevman))
+       if (!sdev && idevman->isAutoAdd(idevman))
        {
                WLog_Print(urbdrc->log, WLOG_TRACE, "Auto Find Device: %04x:%04x ", idVendor, idProduct);
                found = TRUE;
        }
 
-       if (found)
+       if (sdev || found)
        {
                success = idevman->register_udevice(idevman, busnum, devnum, searchman->UsbDevice, 0, 0,
                                                    UDEVMAN_FLAG_ADD_BY_ADDR);
        }
 
-       if (success)
+       if (success > 0)
        {
                searchman->UsbDevice++;
                urdbrc_send_virtual_channel_add(idevman->plugin, get_channel(idevman),
                                                5 + searchman->UsbDevice);
 
-               if (found && sdev)
+               if (sdev)
                        searchman->remove(searchman, sdev->idVendor, sdev->idProduct);
        }
 
index 0f29b0c..ae11753 100644 (file)
@@ -163,9 +163,6 @@ struct _IUDEVICE
 
        BOOL (*attach_kernel_driver)(IUDEVICE* idev);
 
-       /* Wait for 5 sec */
-       BOOL (*wait_for_detach)(IUDEVICE* idev);
-
        int (*query_device_port_status)(IUDEVICE* idev, UINT32* UsbdStatus, UINT32* BufferSize,
                                        BYTE* Buffer);
 
@@ -213,7 +210,6 @@ struct _IUDEVMAN
        IUDEVICE* (*get_udevice_by_UsbDevice)(IUDEVMAN* idevman, UINT32 UsbDevice);
 
        /* Extension */
-       int (*check_device_exist_by_id)(IUDEVMAN* idevman, UINT16 idVendor, UINT16 idProduct);
        int (*isAutoAdd)(IUDEVMAN* idevman);
 
        /* Basic state */