Urbrdc fix (#7417)

* fix libusb libusb_device usage (manually unref required usb devices, versus freeing all when we still hold references to the ones we want)
* disabled detach_kernel_driver & attach_kernel_driver on win32 since libusb does not support them
* fixed libusb async event handling

* add log for transfer request error

* Update libusb_udevice.c

* refactor code
This commit is contained in:
Alexandru Bagu 2021-11-03 06:11:36 -04:00 committed by GitHub
parent 68eb6e4afc
commit 21ca4a009d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 88 additions and 60 deletions

View File

@ -1752,6 +1752,13 @@ static UINT urbdrc_process_transfer_request(IUDEVICE* pdev, URBDRC_CHANNEL_CALLB
break;
}
if (error)
{
WLog_Print(urbdrc->log, WLOG_WARN,
"USB transfer request URB Function %08" PRIx32 " failed with %08" PRIx32,
URB_Function, error);
}
return error;
}

View File

@ -501,17 +501,19 @@ static LIBUSB_DEVICE* udev_get_libusb_dev(libusb_context* context, uint8_t bus_n
for (i = 0; i < total_device; 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))
LIBUSB_DEVICE* dev = libusb_list[i];
if ((bus_number == libusb_get_bus_number(dev)) &&
(dev_number == libusb_get_device_address(dev)))
{
device = libusb_list[i];
break;
device = dev;
}
else
{
libusb_unref_device(dev);
}
}
libusb_free_device_list(libusb_list, 1);
libusb_free_device_list(libusb_list, 0);
return device;
}
@ -533,7 +535,6 @@ static LIBUSB_DEVICE_DESCRIPTOR* udev_new_descript(URBDRC_PLUGIN* urbdrc, LIBUSB
return descriptor;
}
static int libusb_udev_select_interface(IUDEVICE* idev, BYTE InterfaceNumber, BYTE AlternateSetting)
{
int error = 0, diff = 0;
@ -1023,6 +1024,9 @@ static BOOL libusb_udev_detach_kernel_driver(IUDEVICE* idev)
if (!pdev || !pdev->LibusbConfig || !pdev->libusb_handle || !pdev->urbdrc)
return FALSE;
#ifdef _WIN32
return TRUE;
#else
urbdrc = pdev->urbdrc;
if ((pdev->status & URBDRC_DEVICE_DETACH_KERNEL) == 0)
@ -1043,6 +1047,7 @@ static BOOL libusb_udev_detach_kernel_driver(IUDEVICE* idev)
}
return TRUE;
#endif
}
static BOOL libusb_udev_attach_kernel_driver(IUDEVICE* idev)
@ -1059,12 +1064,14 @@ static BOOL libusb_udev_attach_kernel_driver(IUDEVICE* idev)
log_libusb_result(pdev->urbdrc->log, WLOG_DEBUG, "libusb_release_interface", err);
#ifndef _WIN32
if (err != LIBUSB_ERROR_NO_DEVICE)
{
err = libusb_attach_kernel_driver(pdev->libusb_handle, i);
log_libusb_result(pdev->urbdrc->log, WLOG_DEBUG, "libusb_attach_kernel_driver if=%d",
err, i);
}
#endif
}
return TRUE;
@ -1485,6 +1492,7 @@ static void udev_free(IUDEVICE* idev)
ArrayList_Free(udev->request_queue);
/* free the config descriptor that send from windows */
msusb_msconfig_free(udev->MsConfig);
libusb_unref_device(udev->libusb_dev);
libusb_close(udev->libusb_handle);
libusb_close(udev->hub_handle);
free(udev->devDescriptor);
@ -1533,8 +1541,8 @@ static void udev_load_interface(UDEVICE* pdev)
pdev->iface.free = udev_free;
}
static int udev_get_hub_handle(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UDEVICE* pdev,
UINT16 bus_number, UINT16 dev_number)
static int udev_get_device_handle(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UDEVICE* pdev,
UINT16 bus_number, UINT16 dev_number)
{
int error;
ssize_t i, total_device;
@ -1546,21 +1554,19 @@ static int udev_get_hub_handle(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UDEVI
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]);
LIBUSB_DEVICE* dev = libusb_list[i];
if ((bus_number != cbus) || (dev_number != caddr))
if ((bus_number != libusb_get_bus_number(dev)) ||
(dev_number != libusb_get_device_address(dev)))
continue;
error = libusb_open(libusb_list[i], &handle);
error = libusb_open(dev, &pdev->libusb_handle);
if (log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_open", error))
break;
/* get port number */
error = libusb_get_port_numbers(libusb_list[i], port_numbers, sizeof(port_numbers));
libusb_close(handle);
error = libusb_get_port_numbers(dev, port_numbers, sizeof(port_numbers));
if (error < 1)
{
@ -1578,29 +1584,40 @@ static int udev_get_hub_handle(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UDEVI
WLog_Print(urbdrc->log, WLOG_DEBUG, " DevPath: %s", pdev->path);
break;
}
libusb_free_device_list(libusb_list, 1);
if (error < 0)
return -1;
return 0;
}
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;
LIBUSB_DEVICE** libusb_list;
LIBUSB_DEVICE_HANDLE* handle;
total_device = libusb_get_device_list(ctx, &libusb_list);
/* Look for device hub. */
if (error == 0)
error = -1;
for (i = 0; i < total_device; i++)
{
error = -1;
LIBUSB_DEVICE* dev = libusb_list[i];
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(dev)) ||
(1 != libusb_get_device_address(dev))) /* Root hub allways first on bus. */
continue;
if ((bus_number != cbus) || (1 != caddr)) /* Root hub allways first on bus. */
continue;
WLog_Print(urbdrc->log, WLOG_DEBUG, " Open hub: %" PRIu16 "", bus_number);
error = libusb_open(dev, &handle);
WLog_Print(urbdrc->log, WLOG_DEBUG, " Open hub: %" PRIu16 "", bus_number);
error = libusb_open(libusb_list[i], &handle);
if (!log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_open", error))
pdev->hub_handle = handle;
if (!log_libusb_result(urbdrc->log, WLOG_ERROR, "libusb_open", error))
pdev->hub_handle = handle;
break;
}
break;
}
libusb_free_device_list(libusb_list, 1);
@ -1651,30 +1668,26 @@ static IUDEVICE* udev_init(URBDRC_PLUGIN* urbdrc, libusb_context* context, LIBUS
if (urbdrc->listener_callback)
udev_set_channelManager(&pdev->iface, urbdrc->listener_callback->channel_mgr);
/* Get DEVICE handle */
status = udev_get_device_handle(urbdrc, context, pdev, bus_number, dev_number);
if (status != LIBUSB_SUCCESS)
{
struct libusb_device_descriptor desc;
const uint8_t port = libusb_get_port_number(pdev->libusb_dev);
libusb_get_device_descriptor(pdev->libusb_dev, &desc);
log_libusb_result(urbdrc->log, WLOG_ERROR,
"libusb_open [b=0x%02X,p=0x%02X,a=0x%02X,VID=0x%04X,PID=0x%04X]", status,
bus_number, port, dev_number, desc.idVendor, desc.idProduct);
goto fail;
}
/* Get HUB handle */
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)
{
log_libusb_result(urbdrc->log, WLOG_ERROR,
"libusb_open [b=0x%02X,p=0x%02X,a=0x%02X,VID=0x%04X,PID=0x%04X]",
status, bus, port, addr, desc.idVendor, desc.idProduct);
goto fail;
}
}
pdev->devDescriptor = udev_new_descript(urbdrc, pdev->libusb_dev);
if (!pdev->devDescriptor)
@ -1745,8 +1758,6 @@ size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UINT16 idVendo
{
LIBUSB_DEVICE** libusb_list;
UDEVICE** array;
UINT16 bus_number;
UINT16 dev_number;
ssize_t i, total_device;
size_t num = 0;
@ -1763,23 +1774,27 @@ size_t udev_new_by_id(URBDRC_PLUGIN* urbdrc, libusb_context* ctx, UINT16 idVendo
for (i = 0; i < total_device; i++)
{
LIBUSB_DEVICE_DESCRIPTOR* descriptor = udev_new_descript(urbdrc, libusb_list[i]);
LIBUSB_DEVICE* dev = libusb_list[i];
LIBUSB_DEVICE_DESCRIPTOR* descriptor = udev_new_descript(urbdrc, dev);
if ((descriptor->idVendor == idVendor) && (descriptor->idProduct == 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, ctx, libusb_list[i], bus_number, dev_number);
array[num] = (PUDEVICE)udev_init(urbdrc, ctx, dev, libusb_get_bus_number(dev),
libusb_get_device_address(dev));
if (array[num] != NULL)
num++;
}
else
{
libusb_unref_device(dev);
}
free(descriptor);
}
fail:
libusb_free_device_list(libusb_list, 1);
libusb_free_device_list(libusb_list, 0);
*devArray = (IUDEVICE**)array;
return num;
}

View File

@ -195,6 +195,12 @@ static size_t udevman_register_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE
/* register all device that match pid vid */
num = udev_new_by_id(urbdrc, udevman->context, idVendor, idProduct, &devArray);
if (num == 0)
{
WLog_Print(urbdrc->log, WLOG_WARN,
"Could not find or redirect any usb devices by id %04x:%04x", idVendor, idProduct);
}
for (i = 0; i < num; i++)
{
UINT32 id;
@ -835,7 +841,7 @@ static BOOL poll_libusb_events(UDEVMAN* udevman)
{
int rc = LIBUSB_SUCCESS;
struct timeval tv = { 0, 500 };
if (libusb_try_lock_events(udevman->context))
if (libusb_try_lock_events(udevman->context) == 0)
{
if (libusb_event_handling_ok(udevman->context))
{
@ -924,7 +930,7 @@ UINT freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS
udevman->next_device_id = BASE_USBDEVICE_NUM;
udevman->iface.plugin = pEntryPoints->plugin;
rc = libusb_init(&udevman->context);
if (rc != LIBUSB_SUCCESS)
goto fail;