27#include <winpr/cmdline.h>
28#include <winpr/collections.h>
30#include <freerdp/addin.h>
32#include "urbdrc_types.h"
33#include "urbdrc_main.h"
35#include "libusb_udevice.h"
39#if !defined(LIBUSB_HOTPLUG_NO_FLAGS)
40#define LIBUSB_HOTPLUG_NO_FLAGS 0
43#define BASIC_STATE_FUNC_DEFINED(_arg, _type) \
44 static _type udevman_get_##_arg(IUDEVMAN* idevman) \
46 UDEVMAN* udevman = (UDEVMAN*)idevman; \
47 return udevman->_arg; \
49 static void udevman_set_##_arg(IUDEVMAN* idevman, _type _t) \
51 UDEVMAN* udevman = (UDEVMAN*)idevman; \
55#define BASIC_STATE_FUNC_REGISTER(_arg, _man) \
56 _man->iface.get_##_arg = udevman_get_##_arg; \
57 (_man)->iface.set_##_arg = udevman_set_##_arg
73 LPCSTR devices_vid_pid;
75 wArrayList* hotplug_vid_pids;
78 UINT32 next_device_id;
81 HANDLE devman_loading;
82 libusb_context* context;
86typedef UDEVMAN* PUDEVMAN;
88static BOOL poll_libusb_events(UDEVMAN* udevman);
90static void udevman_rewind(IUDEVMAN* idevman)
92 UDEVMAN* udevman = (UDEVMAN*)idevman;
93 udevman->idev = udevman->head;
96static BOOL udevman_has_next(IUDEVMAN* idevman)
98 UDEVMAN* udevman = (UDEVMAN*)idevman;
100 if (!udevman || !udevman->idev)
106static IUDEVICE* udevman_get_next(IUDEVMAN* idevman)
108 UDEVMAN* udevman = (UDEVMAN*)idevman;
109 IUDEVICE* pdev = NULL;
110 pdev = udevman->idev;
111 udevman->idev = (IUDEVICE*)((
UDEVICE*)udevman->idev)->next;
115static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number)
117 IUDEVICE* dev = NULL;
122 idevman->loading_lock(idevman);
123 idevman->rewind(idevman);
125 while (idevman->has_next(idevman))
127 IUDEVICE* pdev = idevman->get_next(idevman);
129 if ((pdev->get_bus_number(pdev) == bus_number) &&
130 (pdev->get_dev_number(pdev) == dev_number))
137 idevman->loading_unlock(idevman);
141static size_t udevman_register_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number,
142 UINT16 idVendor, UINT16 idProduct, UINT32 flag)
144 UDEVMAN* udevman = (UDEVMAN*)idevman;
145 IUDEVICE* pdev = NULL;
146 IUDEVICE** devArray = NULL;
151 if (!idevman || !idevman->plugin)
155 pdev = udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
160 if (flag & UDEVMAN_FLAG_ADD_BY_ADDR)
163 IUDEVICE* tdev = udev_new_by_addr(urbdrc, udevman->context, bus_number, dev_number);
168 id = idevman->get_next_device_id(idevman);
169 tdev->set_UsbDevice(tdev,
id);
170 idevman->loading_lock(idevman);
172 if (udevman->head == NULL)
175 udevman->head = tdev;
176 udevman->tail = tdev;
181 udevman->tail->set_p_next(udevman->tail, tdev);
182 tdev->set_p_prev(tdev, udevman->tail);
183 udevman->tail = tdev;
186 udevman->device_num += 1;
187 idevman->loading_unlock(idevman);
189 else if (flag & UDEVMAN_FLAG_ADD_BY_VID_PID)
193 num = udev_new_by_id(urbdrc, udevman->context, idVendor, idProduct, &devArray);
197 WLog_Print(urbdrc->log, WLOG_WARN,
198 "Could not find or redirect any usb devices by id %04x:%04x", idVendor,
202 for (
size_t i = 0; i < num; i++)
205 IUDEVICE* tdev = devArray[i];
207 if (udevman_get_udevice_by_addr(idevman, tdev->get_bus_number(tdev),
208 tdev->get_dev_number(tdev)) != NULL)
215 id = idevman->get_next_device_id(idevman);
216 tdev->set_UsbDevice(tdev,
id);
217 idevman->loading_lock(idevman);
219 if (udevman->head == NULL)
222 udevman->head = tdev;
223 udevman->tail = tdev;
228 udevman->tail->set_p_next(udevman->tail, tdev);
229 tdev->set_p_prev(tdev, udevman->tail);
230 udevman->tail = tdev;
233 udevman->device_num += 1;
234 idevman->loading_unlock(idevman);
238 free((
void*)devArray);
243 WLog_Print(urbdrc->log, WLOG_ERROR,
"udevman_register_udevice: Invalid flag=%08" PRIx32,
251static BOOL udevman_unregister_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number)
253 UDEVMAN* udevman = (UDEVMAN*)idevman;
255 UDEVICE* dev = (
UDEVICE*)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
257 if (!dev || !idevman)
260 idevman->loading_lock(idevman);
261 idevman->rewind(idevman);
263 while (idevman->has_next(idevman))
265 pdev = (
UDEVICE*)idevman->get_next(idevman);
270 if (dev->prev != NULL)
274 pdev->next = dev->next;
279 udevman->head = (IUDEVICE*)dev->next;
284 if (dev->next != NULL)
288 pdev->prev = dev->prev;
293 udevman->tail = (IUDEVICE*)dev->prev;
296 udevman->device_num--;
301 idevman->loading_unlock(idevman);
305 dev->iface.free(&dev->iface);
313static BOOL udevman_unregister_all_udevices(IUDEVMAN* idevman)
315 UDEVMAN* udevman = (UDEVMAN*)idevman;
323 idevman->loading_lock(idevman);
324 idevman->rewind(idevman);
326 while (idevman->has_next(idevman))
334 if (dev->prev != NULL)
338 pdev->next = dev->next;
343 udevman->head = (IUDEVICE*)dev->next;
348 if (dev->next != NULL)
352 pdev->prev = dev->prev;
357 udevman->tail = (IUDEVICE*)dev->prev;
360 dev->iface.free(&dev->iface);
361 udevman->device_num--;
364 idevman->loading_unlock(idevman);
369static int udevman_is_auto_add(IUDEVMAN* idevman)
371 UDEVMAN* udevman = (UDEVMAN*)idevman;
372 return (udevman->flags & UDEVMAN_FLAG_ADD_BY_AUTO) ? 1 : 0;
375static IUDEVICE* udevman_get_udevice_by_UsbDevice(IUDEVMAN* idevman, UINT32 UsbDevice)
380 if (!idevman || !idevman->plugin)
384 UsbDevice = UsbDevice & INTERFACE_ID_MASK;
386 idevman->loading_lock(idevman);
387 idevman->rewind(idevman);
389 while (idevman->has_next(idevman))
391 pdev = (
UDEVICE*)idevman->get_next(idevman);
393 if (pdev->UsbDevice == UsbDevice)
395 idevman->loading_unlock(idevman);
396 return (IUDEVICE*)pdev;
400 idevman->loading_unlock(idevman);
401 WLog_Print(urbdrc->log, WLOG_WARN,
"Failed to find a USB device mapped to deviceId=%08" PRIx32,
406static IUDEVICE* udevman_get_udevice_by_ChannelID(IUDEVMAN* idevman, UINT32 channelID)
411 if (!idevman || !idevman->plugin)
416 idevman->loading_lock(idevman);
417 idevman->rewind(idevman);
419 while (idevman->has_next(idevman))
421 pdev = (
UDEVICE*)idevman->get_next(idevman);
423 if (pdev->channelID == channelID)
425 idevman->loading_unlock(idevman);
426 return (IUDEVICE*)pdev;
430 idevman->loading_unlock(idevman);
431 WLog_Print(urbdrc->log, WLOG_WARN,
"Failed to find a USB device mapped to channelID=%08" PRIx32,
436static void udevman_loading_lock(IUDEVMAN* idevman)
438 UDEVMAN* udevman = (UDEVMAN*)idevman;
439 (void)WaitForSingleObject(udevman->devman_loading, INFINITE);
442static void udevman_loading_unlock(IUDEVMAN* idevman)
444 UDEVMAN* udevman = (UDEVMAN*)idevman;
445 (void)ReleaseMutex(udevman->devman_loading);
448BASIC_STATE_FUNC_DEFINED(device_num, UINT32)
450static UINT32 udevman_get_next_device_id(IUDEVMAN* idevman)
452 UDEVMAN* udevman = (UDEVMAN*)idevman;
453 return udevman->next_device_id++;
456static void udevman_set_next_device_id(IUDEVMAN* idevman, UINT32 _t)
458 UDEVMAN* udevman = (UDEVMAN*)idevman;
459 udevman->next_device_id = _t;
462static void udevman_free(IUDEVMAN* idevman)
464 UDEVMAN* udevman = (UDEVMAN*)idevman;
469 udevman->running = FALSE;
472 (void)WaitForSingleObject(udevman->thread, INFINITE);
473 (void)CloseHandle(udevman->thread);
476 udevman_unregister_all_udevices(idevman);
478 if (udevman->devman_loading)
479 (void)CloseHandle(udevman->devman_loading);
481 libusb_exit(udevman->context);
483 ArrayList_Free(udevman->hotplug_vid_pids);
487static BOOL filter_by_class(uint8_t bDeviceClass, uint8_t bDeviceSubClass)
489 switch (bDeviceClass)
491 case LIBUSB_CLASS_AUDIO:
492 case LIBUSB_CLASS_HID:
493 case LIBUSB_CLASS_MASS_STORAGE:
494 case LIBUSB_CLASS_HUB:
495 case LIBUSB_CLASS_SMART_CARD:
501 switch (bDeviceSubClass)
510static BOOL append(
char* dst,
size_t length,
const char* src)
512 return winpr_str_append(src, dst, length, NULL);
515static BOOL device_is_filtered(
struct libusb_device* dev,
516 const struct libusb_device_descriptor* desc,
517 libusb_hotplug_event event)
519 char buffer[8192] = { 0 };
521 BOOL filtered = FALSE;
522 append(buffer,
sizeof(buffer), usb_interface_class_to_string(desc->bDeviceClass));
523 if (filter_by_class(desc->bDeviceClass, desc->bDeviceSubClass))
526 switch (desc->bDeviceClass)
528 case LIBUSB_CLASS_PER_INTERFACE:
530 struct libusb_config_descriptor* config = NULL;
531 int rc = libusb_get_active_config_descriptor(dev, &config);
532 if (rc == LIBUSB_SUCCESS)
534 for (uint8_t x = 0; x < config->bNumInterfaces; x++)
536 const struct libusb_interface* ifc = &config->interface[x];
537 for (
int y = 0; y < ifc->num_altsetting; y++)
539 const struct libusb_interface_descriptor*
const alt = &ifc->altsetting[y];
540 if (filter_by_class(alt->bInterfaceClass, alt->bInterfaceSubClass))
543 append(buffer,
sizeof(buffer),
"|");
544 append(buffer,
sizeof(buffer),
545 usb_interface_class_to_string(alt->bInterfaceClass));
549 libusb_free_config_descriptor(config);
562 case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
563 what =
"Hotplug remove";
565 case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
566 what =
"Hotplug add";
569 what =
"Hotplug unknown";
574 WLog_DBG(TAG,
"%s device VID=0x%04X,PID=0x%04X class %s", what, desc->idVendor, desc->idProduct,
579static int LIBUSB_CALL hotplug_callback(
struct libusb_context* ctx,
struct libusb_device* dev,
580 libusb_hotplug_event event,
void* user_data)
583 struct libusb_device_descriptor desc;
584 UDEVMAN* udevman = (UDEVMAN*)user_data;
585 const uint8_t bus = libusb_get_bus_number(dev);
586 const uint8_t addr = libusb_get_device_address(dev);
587 int rc = libusb_get_device_descriptor(dev, &desc);
591 if (rc != LIBUSB_SUCCESS)
596 case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
597 pair.vid = desc.idVendor;
598 pair.pid = desc.idProduct;
599 if ((ArrayList_Contains(udevman->hotplug_vid_pids, &pair)) ||
600 (udevman->iface.isAutoAdd(&udevman->iface) &&
601 !device_is_filtered(dev, &desc, event)))
603 add_device(&udevman->iface, DEVICE_ADD_FLAG_ALL, bus, addr, desc.idVendor,
608 case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
609 del_device(&udevman->iface, DEVICE_ADD_FLAG_ALL, bus, addr, desc.idVendor,
620static BOOL udevman_initialize(IUDEVMAN* idevman, UINT32 channelId)
622 UDEVMAN* udevman = (UDEVMAN*)idevman;
627 idevman->status &= (uint32_t)~URBDRC_DEVICE_CHANNEL_CLOSED;
628 idevman->controlChannelId = channelId;
632static BOOL udevman_vid_pid_pair_equals(
const void* objA,
const void* objB)
634 const VID_PID_PAIR* a = objA;
635 const VID_PID_PAIR* b = objB;
637 return (a->vid == b->vid) && (a->pid == b->pid);
640static BOOL udevman_parse_device_id_addr(
const char** str, UINT16* id1, UINT16* id2, UINT16 max,
641 char split_sign,
char delimiter)
645 unsigned long rc = 0;
647 rc = strtoul(*str, &mid, 16);
649 if ((mid == *str) || (*mid != split_sign) || (rc > max))
653 rc = strtoul(++mid, &end, 16);
655 if ((end == mid) || (rc > max))
663 if (*end == delimiter)
672static UINT urbdrc_udevman_register_devices(UDEVMAN* udevman,
const char* devices, BOOL add_by_addr)
674 const char* pos = devices;
680 if (!udevman_parse_device_id_addr(&pos, &id1, &id2, (add_by_addr) ? UINT8_MAX : UINT16_MAX,
683 WLog_ERR(TAG,
"Invalid device argument: \"%s\"", devices);
684 return CHANNEL_RC_INITIALIZATION_ERROR;
689 if (!add_device(&udevman->iface, DEVICE_ADD_FLAG_BUS | DEVICE_ADD_FLAG_DEV, (UINT8)id1,
691 return CHANNEL_RC_INITIALIZATION_ERROR;
695 VID_PID_PAIR* idpair = calloc(1,
sizeof(VID_PID_PAIR));
697 return CHANNEL_RC_NO_MEMORY;
700 if (!ArrayList_Append(udevman->hotplug_vid_pids, idpair))
703 return CHANNEL_RC_NO_MEMORY;
707 if (!add_device(&udevman->iface, DEVICE_ADD_FLAG_VENDOR | DEVICE_ADD_FLAG_PRODUCT, 0, 0,
711 return CHANNEL_RC_INITIALIZATION_ERROR;
717 return CHANNEL_RC_OK;
720static UINT urbdrc_udevman_parse_addin_args(UDEVMAN* udevman,
const ADDIN_ARGV* args)
722 LPCSTR devices = NULL;
724 for (
int x = 0; x < args->argc; x++)
726 const char* arg = args->argv[x];
727 if (strcmp(arg,
"dbg") == 0)
729 WLog_SetLogLevel(WLog_Get(TAG), WLOG_TRACE);
731 else if (_strnicmp(arg,
"device:", 7) == 0)
734 const char* val = &arg[7];
735 const size_t len = strlen(val);
736 if (strcmp(val,
"*") == 0)
738 udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
740 else if (_strnicmp(arg,
"USBInstanceID:", 14) == 0)
744 else if ((val[0] ==
'{') && (val[len - 1] ==
'}'))
749 else if (_strnicmp(arg,
"dev:", 4) == 0)
753 else if (_strnicmp(arg,
"id", 2) == 0)
755 const char* p = strchr(arg,
':');
757 udevman->devices_vid_pid = p + 1;
759 udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
761 else if (_strnicmp(arg,
"addr", 4) == 0)
763 const char* p = strchr(arg,
':');
765 udevman->devices_addr = p + 1;
767 udevman->flags = UDEVMAN_FLAG_ADD_BY_ADDR;
769 else if (strcmp(arg,
"auto") == 0)
771 udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
775 const size_t len = strlen(arg);
776 if ((arg[0] ==
'{') && (arg[len - 1] ==
'}'))
784 if (udevman->flags & UDEVMAN_FLAG_ADD_BY_VID_PID)
785 udevman->devices_vid_pid = devices;
786 else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR)
787 udevman->devices_addr = devices;
790 return CHANNEL_RC_OK;
793static UINT udevman_listener_created_callback(IUDEVMAN* iudevman)
795 UDEVMAN* udevman = (UDEVMAN*)iudevman;
796 WINPR_ASSERT(udevman);
798 if (udevman->devices_vid_pid)
799 return urbdrc_udevman_register_devices(udevman, udevman->devices_vid_pid, FALSE);
801 if (udevman->devices_addr)
802 return urbdrc_udevman_register_devices(udevman, udevman->devices_addr, TRUE);
804 return CHANNEL_RC_OK;
807static void udevman_load_interface(UDEVMAN* udevman)
810 udevman->iface.free = udevman_free;
812 udevman->iface.rewind = udevman_rewind;
813 udevman->iface.get_next = udevman_get_next;
814 udevman->iface.has_next = udevman_has_next;
815 udevman->iface.register_udevice = udevman_register_udevice;
816 udevman->iface.unregister_udevice = udevman_unregister_udevice;
817 udevman->iface.get_udevice_by_UsbDevice = udevman_get_udevice_by_UsbDevice;
818 udevman->iface.get_udevice_by_ChannelID = udevman_get_udevice_by_ChannelID;
820 udevman->iface.isAutoAdd = udevman_is_auto_add;
822 BASIC_STATE_FUNC_REGISTER(device_num, udevman);
823 BASIC_STATE_FUNC_REGISTER(next_device_id, udevman);
826 udevman->iface.loading_lock = udevman_loading_lock;
827 udevman->iface.loading_unlock = udevman_loading_unlock;
828 udevman->iface.initialize = udevman_initialize;
829 udevman->iface.listener_created_callback = udevman_listener_created_callback;
832static BOOL poll_libusb_events(UDEVMAN* udevman)
834 int rc = LIBUSB_SUCCESS;
835 struct timeval tv = { 0, 500 };
836 if (libusb_try_lock_events(udevman->context) == 0)
838 if (libusb_event_handling_ok(udevman->context))
840 rc = libusb_handle_events_locked(udevman->context, &tv);
841 if (rc != LIBUSB_SUCCESS)
842 WLog_WARN(TAG,
"libusb_handle_events_locked %d", rc);
844 libusb_unlock_events(udevman->context);
848 libusb_lock_event_waiters(udevman->context);
849 if (libusb_event_handler_active(udevman->context))
851 rc = libusb_wait_for_event(udevman->context, &tv);
852 if (rc < LIBUSB_SUCCESS)
853 WLog_WARN(TAG,
"libusb_wait_for_event %d", rc);
855 libusb_unlock_event_waiters(udevman->context);
861static DWORD WINAPI poll_thread(LPVOID lpThreadParameter)
863 libusb_hotplug_callback_handle handle = 0;
864 UDEVMAN* udevman = (UDEVMAN*)lpThreadParameter;
865 BOOL hasHotplug = libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG);
869 int rc = libusb_hotplug_register_callback(
871 LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
872 LIBUSB_HOTPLUG_NO_FLAGS, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
873 LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, udevman, &handle);
875 if (rc != LIBUSB_SUCCESS)
876 udevman->running = FALSE;
879 WLog_WARN(TAG,
"Platform does not support libusb hotplug. USB devices plugged in later "
880 "will not be detected.");
882 while (udevman->running)
884 poll_libusb_events(udevman);
888 libusb_hotplug_deregister_callback(udevman->context, handle);
891 while (poll_libusb_events(udevman))
898FREERDP_ENTRY_POINT(UINT VCAPITYPE libusb_freerdp_urbdrc_client_subsystem_entry(
903 UDEVMAN* udevman = NULL;
905 udevman = (PUDEVMAN)calloc(1,
sizeof(UDEVMAN));
910 udevman->hotplug_vid_pids = ArrayList_New(TRUE);
911 if (!udevman->hotplug_vid_pids)
913 obj = ArrayList_Object(udevman->hotplug_vid_pids);
914 obj->fnObjectFree = free;
915 obj->fnObjectEquals = udevman_vid_pid_pair_equals;
917 udevman->next_device_id = BASE_USBDEVICE_NUM;
918 udevman->iface.plugin = pEntryPoints->plugin;
919 const int res = libusb_init(&udevman->context);
921 if (res != LIBUSB_SUCCESS)
925#if LIBUSB_API_VERSION >= 0x01000106
927 const int rc = libusb_set_option(udevman->context, LIBUSB_OPTION_USE_USBDK);
932 case LIBUSB_ERROR_NOT_FOUND:
933 case LIBUSB_ERROR_NOT_SUPPORTED:
934 WLog_WARN(TAG,
"LIBUSB_OPTION_USE_USBDK %s [%d]", libusb_strerror(rc), rc);
937 WLog_ERR(TAG,
"LIBUSB_OPTION_USE_USBDK %s [%d]", libusb_strerror(rc), rc);
943 udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
944 udevman->devman_loading = CreateMutexA(NULL, FALSE,
"devman_loading");
946 if (!udevman->devman_loading)
950 udevman_load_interface(udevman);
951 status = urbdrc_udevman_parse_addin_args(udevman, args);
953 if (status != CHANNEL_RC_OK)
956 udevman->running = TRUE;
957 udevman->thread = CreateThread(NULL, 0, poll_thread, udevman, 0, NULL);
959 if (!udevman->thread)
962 if (!pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*)udevman))
965 WLog_DBG(TAG,
"UDEVMAN device registered.");
968 udevman_free(&udevman->iface);
969 return ERROR_INTERNAL_ERROR;
This struct contains function pointer to initialize/free objects.