mirror of
https://github.com/morgan9e/FreeRDP
synced 2026-04-15 00:44:19 +09:00
Fix #5910: USB hotplug added device wrong
When a USB device was added via hotplug add_device was called with wrong arguments.
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/* 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);
|
||||
if (pdev->channelManager)
|
||||
channel = IFCALLRESULT(NULL, pdev->channelManager->FindChannelById,
|
||||
pdev->channelManager, pdev->channelID);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user