From acb77391a2c6735040866bad40955e3aacd961a8 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 26 Feb 2020 12:24:25 +0100 Subject: [PATCH] Fix #5910: USB hotplug added device wrong When a USB device was added via hotplug add_device was called with wrong arguments. --- channels/urbdrc/client/data_transfer.c | 6 +- channels/urbdrc/client/libusb/libusb_udevice.c | 193 +++++++++++++++++-------- channels/urbdrc/client/libusb/libusb_udevice.h | 6 +- channels/urbdrc/client/libusb/libusb_udevman.c | 125 ++++++++++++++-- channels/urbdrc/client/searchman.c | 47 ++++-- channels/urbdrc/client/searchman.h | 5 +- channels/urbdrc/client/urbdrc_main.c | 25 +--- channels/urbdrc/client/urbdrc_main.h | 4 - 8 files changed, 291 insertions(+), 120 deletions(-) diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c index 1e71edd..25918b8 100644 --- a/channels/urbdrc/client/data_transfer.c +++ b/channels/urbdrc/client/data_transfer.c @@ -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; } diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c index 0c53b30..0801c00 100644 --- a/channels/urbdrc/client/libusb/libusb_udevice.c +++ b/channels/urbdrc/client/libusb/libusb_udevice.c @@ -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); } diff --git a/channels/urbdrc/client/libusb/libusb_udevice.h b/channels/urbdrc/client/libusb/libusb_udevice.h index 246f1e0..cf421d0 100644 --- a/channels/urbdrc/client/libusb/libusb_udevice.h +++ b/channels/urbdrc/client/libusb/libusb_udevice.h @@ -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 */ diff --git a/channels/urbdrc/client/libusb/libusb_udevman.c b/channels/urbdrc/client/libusb/libusb_udevman.c index d7a7d8d..40c39ae 100644 --- a/channels/urbdrc/client/libusb/libusb_udevman.c +++ b/channels/urbdrc/client/libusb/libusb_udevman.c @@ -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); diff --git a/channels/urbdrc/client/searchman.c b/channels/urbdrc/client/searchman.c index 6d109f2..39bb5ee 100644 --- a/channels/urbdrc/client/searchman.c +++ b/channels/urbdrc/client/searchman.c @@ -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; } diff --git a/channels/urbdrc/client/searchman.h b/channels/urbdrc/client/searchman.h index 4e29f0d..4f1d316 100644 --- a/channels/urbdrc/client/searchman.h +++ b/channels/urbdrc/client/searchman.h @@ -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); }; diff --git a/channels/urbdrc/client/urbdrc_main.c b/channels/urbdrc/client/urbdrc_main.c index 4bc3cfb..dfdf1ce 100644 --- a/channels/urbdrc/client/urbdrc_main.c +++ b/channels/urbdrc/client/urbdrc_main.c @@ -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); } diff --git a/channels/urbdrc/client/urbdrc_main.h b/channels/urbdrc/client/urbdrc_main.h index 0f29b0c..ae11753 100644 --- a/channels/urbdrc/client/urbdrc_main.h +++ b/channels/urbdrc/client/urbdrc_main.h @@ -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 */ -- 2.7.4