FreeRDP
libusb_udevman.c
1 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 
26 #include <winpr/crt.h>
27 #include <winpr/cmdline.h>
28 #include <winpr/collections.h>
29 
30 #include <freerdp/addin.h>
31 
32 #include "urbdrc_types.h"
33 #include "urbdrc_main.h"
34 
35 #include "libusb_udevice.h"
36 
37 #include <libusb.h>
38 
39 #if !defined(LIBUSB_HOTPLUG_NO_FLAGS)
40 #define LIBUSB_HOTPLUG_NO_FLAGS 0
41 #endif
42 
43 #define BASIC_STATE_FUNC_DEFINED(_arg, _type) \
44  static _type udevman_get_##_arg(IUDEVMAN* idevman) \
45  { \
46  UDEVMAN* udevman = (UDEVMAN*)idevman; \
47  return udevman->_arg; \
48  } \
49  static void udevman_set_##_arg(IUDEVMAN* idevman, _type _t) \
50  { \
51  UDEVMAN* udevman = (UDEVMAN*)idevman; \
52  udevman->_arg = _t; \
53  }
54 
55 #define BASIC_STATE_FUNC_REGISTER(_arg, _man) \
56  _man->iface.get_##_arg = udevman_get_##_arg; \
57  (_man)->iface.set_##_arg = udevman_set_##_arg
58 
59 typedef struct
60 {
61  UINT16 vid;
62  UINT16 pid;
63 } VID_PID_PAIR;
64 
65 typedef struct
66 {
67  IUDEVMAN iface;
68 
69  IUDEVICE* idev; /* iterator device */
70  IUDEVICE* head; /* head device in linked list */
71  IUDEVICE* tail; /* tail device in linked list */
72 
73  LPCSTR devices_vid_pid;
74  LPCSTR devices_addr;
75  wArrayList* hotplug_vid_pids;
76  UINT16 flags;
77  UINT32 device_num;
78  UINT32 next_device_id;
79  UINT32 channel_id;
80 
81  HANDLE devman_loading;
82  libusb_context* context;
83  HANDLE thread;
84  BOOL running;
85 } UDEVMAN;
86 typedef UDEVMAN* PUDEVMAN;
87 
88 static BOOL poll_libusb_events(UDEVMAN* udevman);
89 
90 static void udevman_rewind(IUDEVMAN* idevman)
91 {
92  UDEVMAN* udevman = (UDEVMAN*)idevman;
93  udevman->idev = udevman->head;
94 }
95 
96 static BOOL udevman_has_next(IUDEVMAN* idevman)
97 {
98  UDEVMAN* udevman = (UDEVMAN*)idevman;
99 
100  if (!udevman || !udevman->idev)
101  return FALSE;
102  else
103  return TRUE;
104 }
105 
106 static IUDEVICE* udevman_get_next(IUDEVMAN* idevman)
107 {
108  UDEVMAN* udevman = (UDEVMAN*)idevman;
109  IUDEVICE* pdev = NULL;
110  pdev = udevman->idev;
111  udevman->idev = (IUDEVICE*)((UDEVICE*)udevman->idev)->next;
112  return pdev;
113 }
114 
115 static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number)
116 {
117  IUDEVICE* dev = NULL;
118 
119  if (!idevman)
120  return NULL;
121 
122  idevman->loading_lock(idevman);
123  idevman->rewind(idevman);
124 
125  while (idevman->has_next(idevman))
126  {
127  IUDEVICE* pdev = idevman->get_next(idevman);
128 
129  if ((pdev->get_bus_number(pdev) == bus_number) &&
130  (pdev->get_dev_number(pdev) == dev_number))
131  {
132  dev = pdev;
133  break;
134  }
135  }
136 
137  idevman->loading_unlock(idevman);
138  return dev;
139 }
140 
141 static size_t udevman_register_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number,
142  UINT16 idVendor, UINT16 idProduct, UINT32 flag)
143 {
144  UDEVMAN* udevman = (UDEVMAN*)idevman;
145  IUDEVICE* pdev = NULL;
146  IUDEVICE** devArray = NULL;
147  URBDRC_PLUGIN* urbdrc = NULL;
148  size_t num = 0;
149  size_t addnum = 0;
150 
151  if (!idevman || !idevman->plugin)
152  return 0;
153 
154  urbdrc = (URBDRC_PLUGIN*)idevman->plugin;
155  pdev = udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
156 
157  if (pdev != NULL)
158  return 0;
159 
160  if (flag & UDEVMAN_FLAG_ADD_BY_ADDR)
161  {
162  UINT32 id = 0;
163  IUDEVICE* tdev = udev_new_by_addr(urbdrc, udevman->context, bus_number, dev_number);
164 
165  if (tdev == NULL)
166  return 0;
167 
168  id = idevman->get_next_device_id(idevman);
169  tdev->set_UsbDevice(tdev, id);
170  idevman->loading_lock(idevman);
171 
172  if (udevman->head == NULL)
173  {
174  /* linked list is empty */
175  udevman->head = tdev;
176  udevman->tail = tdev;
177  }
178  else
179  {
180  /* append device to the end of the linked list */
181  udevman->tail->set_p_next(udevman->tail, tdev);
182  tdev->set_p_prev(tdev, udevman->tail);
183  udevman->tail = tdev;
184  }
185 
186  udevman->device_num += 1;
187  idevman->loading_unlock(idevman);
188  }
189  else if (flag & UDEVMAN_FLAG_ADD_BY_VID_PID)
190  {
191  addnum = 0;
192  /* register all device that match pid vid */
193  num = udev_new_by_id(urbdrc, udevman->context, idVendor, idProduct, &devArray);
194 
195  if (num == 0)
196  {
197  WLog_Print(urbdrc->log, WLOG_WARN,
198  "Could not find or redirect any usb devices by id %04x:%04x", idVendor,
199  idProduct);
200  }
201 
202  for (size_t i = 0; i < num; i++)
203  {
204  UINT32 id = 0;
205  IUDEVICE* tdev = devArray[i];
206 
207  if (udevman_get_udevice_by_addr(idevman, tdev->get_bus_number(tdev),
208  tdev->get_dev_number(tdev)) != NULL)
209  {
210  tdev->free(tdev);
211  devArray[i] = NULL;
212  continue;
213  }
214 
215  id = idevman->get_next_device_id(idevman);
216  tdev->set_UsbDevice(tdev, id);
217  idevman->loading_lock(idevman);
218 
219  if (udevman->head == NULL)
220  {
221  /* linked list is empty */
222  udevman->head = tdev;
223  udevman->tail = tdev;
224  }
225  else
226  {
227  /* append device to the end of the linked list */
228  udevman->tail->set_p_next(udevman->tail, tdev);
229  tdev->set_p_prev(tdev, udevman->tail);
230  udevman->tail = tdev;
231  }
232 
233  udevman->device_num += 1;
234  idevman->loading_unlock(idevman);
235  addnum++;
236  }
237 
238  free(devArray);
239  return addnum;
240  }
241  else
242  {
243  WLog_Print(urbdrc->log, WLOG_ERROR, "udevman_register_udevice: Invalid flag=%08" PRIx32,
244  flag);
245  return 0;
246  }
247 
248  return 1;
249 }
250 
251 static BOOL udevman_unregister_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number)
252 {
253  UDEVMAN* udevman = (UDEVMAN*)idevman;
254  UDEVICE* pdev = NULL;
255  UDEVICE* dev = (UDEVICE*)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
256 
257  if (!dev || !idevman)
258  return FALSE;
259 
260  idevman->loading_lock(idevman);
261  idevman->rewind(idevman);
262 
263  while (idevman->has_next(idevman))
264  {
265  pdev = (UDEVICE*)idevman->get_next(idevman);
266 
267  if (pdev == dev) /* device exists */
268  {
269  /* set previous device to point to next device */
270  if (dev->prev != NULL)
271  {
272  /* unregistered device is not the head */
273  pdev = dev->prev;
274  pdev->next = dev->next;
275  }
276  else
277  {
278  /* unregistered device is the head, update head */
279  udevman->head = (IUDEVICE*)dev->next;
280  }
281 
282  /* set next device to point to previous device */
283 
284  if (dev->next != NULL)
285  {
286  /* unregistered device is not the tail */
287  pdev = (UDEVICE*)dev->next;
288  pdev->prev = dev->prev;
289  }
290  else
291  {
292  /* unregistered device is the tail, update tail */
293  udevman->tail = (IUDEVICE*)dev->prev;
294  }
295 
296  udevman->device_num--;
297  break;
298  }
299  }
300 
301  idevman->loading_unlock(idevman);
302 
303  if (dev)
304  {
305  dev->iface.free(&dev->iface);
306  return TRUE; /* unregistration successful */
307  }
308 
309  /* if we reach this point, the device wasn't found */
310  return FALSE;
311 }
312 
313 static BOOL udevman_unregister_all_udevices(IUDEVMAN* idevman)
314 {
315  UDEVMAN* udevman = (UDEVMAN*)idevman;
316 
317  if (!idevman)
318  return FALSE;
319 
320  if (!udevman->head)
321  return TRUE;
322 
323  idevman->loading_lock(idevman);
324  idevman->rewind(idevman);
325 
326  while (idevman->has_next(idevman))
327  {
328  UDEVICE* dev = (UDEVICE*)idevman->get_next(idevman);
329 
330  if (!dev)
331  continue;
332 
333  /* set previous device to point to next device */
334  if (dev->prev != NULL)
335  {
336  /* unregistered device is not the head */
337  UDEVICE* pdev = dev->prev;
338  pdev->next = dev->next;
339  }
340  else
341  {
342  /* unregistered device is the head, update head */
343  udevman->head = (IUDEVICE*)dev->next;
344  }
345 
346  /* set next device to point to previous device */
347 
348  if (dev->next != NULL)
349  {
350  /* unregistered device is not the tail */
351  UDEVICE* pdev = (UDEVICE*)dev->next;
352  pdev->prev = dev->prev;
353  }
354  else
355  {
356  /* unregistered device is the tail, update tail */
357  udevman->tail = (IUDEVICE*)dev->prev;
358  }
359 
360  dev->iface.free(&dev->iface);
361  udevman->device_num--;
362  }
363 
364  idevman->loading_unlock(idevman);
365 
366  return TRUE;
367 }
368 
369 static int udevman_is_auto_add(IUDEVMAN* idevman)
370 {
371  UDEVMAN* udevman = (UDEVMAN*)idevman;
372  return (udevman->flags & UDEVMAN_FLAG_ADD_BY_AUTO) ? 1 : 0;
373 }
374 
375 static IUDEVICE* udevman_get_udevice_by_UsbDevice(IUDEVMAN* idevman, UINT32 UsbDevice)
376 {
377  UDEVICE* pdev = NULL;
378  URBDRC_PLUGIN* urbdrc = NULL;
379 
380  if (!idevman || !idevman->plugin)
381  return NULL;
382 
383  /* Mask highest 2 bits, must be ignored */
384  UsbDevice = UsbDevice & INTERFACE_ID_MASK;
385  urbdrc = (URBDRC_PLUGIN*)idevman->plugin;
386  idevman->loading_lock(idevman);
387  idevman->rewind(idevman);
388 
389  while (idevman->has_next(idevman))
390  {
391  pdev = (UDEVICE*)idevman->get_next(idevman);
392 
393  if (pdev->UsbDevice == UsbDevice)
394  {
395  idevman->loading_unlock(idevman);
396  return (IUDEVICE*)pdev;
397  }
398  }
399 
400  idevman->loading_unlock(idevman);
401  WLog_Print(urbdrc->log, WLOG_WARN, "Failed to find a USB device mapped to deviceId=%08" PRIx32,
402  UsbDevice);
403  return NULL;
404 }
405 
406 static IUDEVICE* udevman_get_udevice_by_ChannelID(IUDEVMAN* idevman, UINT32 channelID)
407 {
408  UDEVICE* pdev = NULL;
409  URBDRC_PLUGIN* urbdrc = NULL;
410 
411  if (!idevman || !idevman->plugin)
412  return NULL;
413 
414  /* Mask highest 2 bits, must be ignored */
415  urbdrc = (URBDRC_PLUGIN*)idevman->plugin;
416  idevman->loading_lock(idevman);
417  idevman->rewind(idevman);
418 
419  while (idevman->has_next(idevman))
420  {
421  pdev = (UDEVICE*)idevman->get_next(idevman);
422 
423  if (pdev->channelID == channelID)
424  {
425  idevman->loading_unlock(idevman);
426  return (IUDEVICE*)pdev;
427  }
428  }
429 
430  idevman->loading_unlock(idevman);
431  WLog_Print(urbdrc->log, WLOG_WARN, "Failed to find a USB device mapped to channelID=%08" PRIx32,
432  channelID);
433  return NULL;
434 }
435 
436 static void udevman_loading_lock(IUDEVMAN* idevman)
437 {
438  UDEVMAN* udevman = (UDEVMAN*)idevman;
439  (void)WaitForSingleObject(udevman->devman_loading, INFINITE);
440 }
441 
442 static void udevman_loading_unlock(IUDEVMAN* idevman)
443 {
444  UDEVMAN* udevman = (UDEVMAN*)idevman;
445  (void)ReleaseMutex(udevman->devman_loading);
446 }
447 
448 BASIC_STATE_FUNC_DEFINED(device_num, UINT32)
449 
450 static UINT32 udevman_get_next_device_id(IUDEVMAN* idevman)
451 {
452  UDEVMAN* udevman = (UDEVMAN*)idevman;
453  return udevman->next_device_id++;
454 }
455 
456 static void udevman_set_next_device_id(IUDEVMAN* idevman, UINT32 _t)
457 {
458  UDEVMAN* udevman = (UDEVMAN*)idevman;
459  udevman->next_device_id = _t;
460 }
461 
462 static void udevman_free(IUDEVMAN* idevman)
463 {
464  UDEVMAN* udevman = (UDEVMAN*)idevman;
465 
466  if (!udevman)
467  return;
468 
469  udevman->running = FALSE;
470  if (udevman->thread)
471  {
472  (void)WaitForSingleObject(udevman->thread, INFINITE);
473  (void)CloseHandle(udevman->thread);
474  }
475 
476  udevman_unregister_all_udevices(idevman);
477 
478  if (udevman->devman_loading)
479  (void)CloseHandle(udevman->devman_loading);
480 
481  libusb_exit(udevman->context);
482 
483  ArrayList_Free(udevman->hotplug_vid_pids);
484  free(udevman);
485 }
486 
487 static BOOL filter_by_class(uint8_t bDeviceClass, uint8_t bDeviceSubClass)
488 {
489  switch (bDeviceClass)
490  {
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:
496  return TRUE;
497  default:
498  break;
499  }
500 
501  switch (bDeviceSubClass)
502  {
503  default:
504  break;
505  }
506 
507  return FALSE;
508 }
509 
510 static BOOL append(char* dst, size_t length, const char* src)
511 {
512  return winpr_str_append(src, dst, length, NULL);
513 }
514 
515 static BOOL device_is_filtered(struct libusb_device* dev,
516  const struct libusb_device_descriptor* desc,
517  libusb_hotplug_event event)
518 {
519  char buffer[8192] = { 0 };
520  char* what = NULL;
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))
524  filtered = TRUE;
525 
526  switch (desc->bDeviceClass)
527  {
528  case LIBUSB_CLASS_PER_INTERFACE:
529  {
530  struct libusb_config_descriptor* config = NULL;
531  int rc = libusb_get_active_config_descriptor(dev, &config);
532  if (rc == LIBUSB_SUCCESS)
533  {
534  for (uint8_t x = 0; x < config->bNumInterfaces; x++)
535  {
536  const struct libusb_interface* ifc = &config->interface[x];
537  for (int y = 0; y < ifc->num_altsetting; y++)
538  {
539  const struct libusb_interface_descriptor* const alt = &ifc->altsetting[y];
540  if (filter_by_class(alt->bInterfaceClass, alt->bInterfaceSubClass))
541  filtered = TRUE;
542 
543  append(buffer, sizeof(buffer), "|");
544  append(buffer, sizeof(buffer),
545  usb_interface_class_to_string(alt->bInterfaceClass));
546  }
547  }
548  }
549  libusb_free_config_descriptor(config);
550  }
551  break;
552  default:
553  break;
554  }
555 
556  if (filtered)
557  what = "Filtered";
558  else
559  {
560  switch (event)
561  {
562  case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
563  what = "Hotplug remove";
564  break;
565  case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
566  what = "Hotplug add";
567  break;
568  default:
569  what = "Hotplug unknown";
570  break;
571  }
572  }
573 
574  WLog_DBG(TAG, "%s device VID=0x%04X,PID=0x%04X class %s", what, desc->idVendor, desc->idProduct,
575  buffer);
576  return filtered;
577 }
578 
579 static int LIBUSB_CALL hotplug_callback(struct libusb_context* ctx, struct libusb_device* dev,
580  libusb_hotplug_event event, void* user_data)
581 {
582  VID_PID_PAIR pair;
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);
588 
589  WINPR_UNUSED(ctx);
590 
591  if (rc != LIBUSB_SUCCESS)
592  return rc;
593 
594  switch (event)
595  {
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)))
602  {
603  add_device(&udevman->iface, DEVICE_ADD_FLAG_ALL, bus, addr, desc.idVendor,
604  desc.idProduct);
605  }
606  break;
607 
608  case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
609  del_device(&udevman->iface, DEVICE_ADD_FLAG_ALL, bus, addr, desc.idVendor,
610  desc.idProduct);
611  break;
612 
613  default:
614  break;
615  }
616 
617  return 0;
618 }
619 
620 static BOOL udevman_initialize(IUDEVMAN* idevman, UINT32 channelId)
621 {
622  UDEVMAN* udevman = (UDEVMAN*)idevman;
623 
624  if (!udevman)
625  return FALSE;
626 
627  idevman->status &= ~URBDRC_DEVICE_CHANNEL_CLOSED;
628  idevman->controlChannelId = channelId;
629  return TRUE;
630 }
631 
632 static BOOL udevman_vid_pid_pair_equals(const void* objA, const void* objB)
633 {
634  const VID_PID_PAIR* a = objA;
635  const VID_PID_PAIR* b = objB;
636 
637  return (a->vid == b->vid) && (a->pid == b->pid);
638 }
639 
640 static BOOL udevman_parse_device_id_addr(const char** str, UINT16* id1, UINT16* id2, UINT16 max,
641  char split_sign, char delimiter)
642 {
643  char* mid = NULL;
644  char* end = NULL;
645  unsigned long rc = 0;
646 
647  rc = strtoul(*str, &mid, 16);
648 
649  if ((mid == *str) || (*mid != split_sign) || (rc > max))
650  return FALSE;
651 
652  *id1 = (UINT16)rc;
653  rc = strtoul(++mid, &end, 16);
654 
655  if ((end == mid) || (rc > max))
656  return FALSE;
657 
658  *id2 = (UINT16)rc;
659 
660  *str += end - *str;
661  if (*end == '\0')
662  return TRUE;
663  if (*end == delimiter)
664  {
665  (*str)++;
666  return TRUE;
667  }
668 
669  return FALSE;
670 }
671 
672 static BOOL urbdrc_udevman_register_devices(UDEVMAN* udevman, const char* devices, BOOL add_by_addr)
673 {
674  const char* pos = devices;
675  VID_PID_PAIR* idpair = NULL;
676  UINT16 id1 = 0;
677  UINT16 id2 = 0;
678 
679  while (*pos != '\0')
680  {
681  if (!udevman_parse_device_id_addr(&pos, &id1, &id2, (add_by_addr) ? UINT8_MAX : UINT16_MAX,
682  ':', '#'))
683  {
684  WLog_ERR(TAG, "Invalid device argument: \"%s\"", devices);
685  return FALSE;
686  }
687 
688  if (add_by_addr)
689  {
690  add_device(&udevman->iface, DEVICE_ADD_FLAG_BUS | DEVICE_ADD_FLAG_DEV, (UINT8)id1,
691  (UINT8)id2, 0, 0);
692  }
693  else
694  {
695  idpair = calloc(1, sizeof(VID_PID_PAIR));
696  if (!idpair)
697  return CHANNEL_RC_NO_MEMORY;
698  idpair->vid = id1;
699  idpair->pid = id2;
700  if (!ArrayList_Append(udevman->hotplug_vid_pids, idpair))
701  {
702  free(idpair);
703  return CHANNEL_RC_NO_MEMORY;
704  }
705 
706  add_device(&udevman->iface, DEVICE_ADD_FLAG_VENDOR | DEVICE_ADD_FLAG_PRODUCT, 0, 0, id1,
707  id2);
708  }
709  }
710 
711  // NOLINTNEXTLINE(clang-analyzer-unix.Malloc): ArrayList_Append owns idpair
712  return CHANNEL_RC_OK;
713 }
714 
715 static UINT urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, const ADDIN_ARGV* args)
716 {
717  LPCSTR devices = NULL;
718 
719  for (int x = 0; x < args->argc; x++)
720  {
721  const char* arg = args->argv[x];
722  if (strcmp(arg, "dbg") == 0)
723  {
724  WLog_SetLogLevel(WLog_Get(TAG), WLOG_TRACE);
725  }
726  else if (_strnicmp(arg, "device:", 7) == 0)
727  {
728  /* Redirect all local devices */
729  const char* val = &arg[7];
730  const size_t len = strlen(val);
731  if (strcmp(val, "*") == 0)
732  {
733  udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
734  }
735  else if (_strnicmp(arg, "USBInstanceID:", 14) == 0)
736  {
737  // TODO: Usb instance ID
738  }
739  else if ((val[0] == '{') && (val[len - 1] == '}'))
740  {
741  // TODO: Usb device class
742  }
743  }
744  else if (_strnicmp(arg, "dev:", 4) == 0)
745  {
746  devices = &arg[4];
747  }
748  else if (_strnicmp(arg, "id", 2) == 0)
749  {
750  const char* p = strchr(arg, ':');
751  if (p)
752  udevman->devices_vid_pid = p + 1;
753  else
754  udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
755  }
756  else if (_strnicmp(arg, "addr", 4) == 0)
757  {
758  const char* p = strchr(arg, ':');
759  if (p)
760  udevman->devices_addr = p + 1;
761  else
762  udevman->flags = UDEVMAN_FLAG_ADD_BY_ADDR;
763  }
764  else if (strcmp(arg, "auto") == 0)
765  {
766  udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
767  }
768  else
769  {
770  const size_t len = strlen(arg);
771  if ((arg[0] == '{') && (arg[len - 1] == '}'))
772  {
773  // TODO: Check for {Device Setup Class GUID}:
774  }
775  }
776  }
777  if (devices)
778  {
779  if (udevman->flags & UDEVMAN_FLAG_ADD_BY_VID_PID)
780  udevman->devices_vid_pid = devices;
781  else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR)
782  udevman->devices_addr = devices;
783  }
784 
785  return CHANNEL_RC_OK;
786 }
787 
788 static UINT udevman_listener_created_callback(IUDEVMAN* iudevman)
789 {
790  UINT status = 0;
791  UDEVMAN* udevman = (UDEVMAN*)iudevman;
792 
793  if (udevman->devices_vid_pid)
794  {
795  status = urbdrc_udevman_register_devices(udevman, udevman->devices_vid_pid, FALSE);
796  if (status != CHANNEL_RC_OK)
797  return status;
798  }
799 
800  if (udevman->devices_addr)
801  return urbdrc_udevman_register_devices(udevman, udevman->devices_addr, TRUE);
802 
803  return CHANNEL_RC_OK;
804 }
805 
806 static void udevman_load_interface(UDEVMAN* udevman)
807 {
808  /* standard */
809  udevman->iface.free = udevman_free;
810  /* manage devices */
811  udevman->iface.rewind = udevman_rewind;
812  udevman->iface.get_next = udevman_get_next;
813  udevman->iface.has_next = udevman_has_next;
814  udevman->iface.register_udevice = udevman_register_udevice;
815  udevman->iface.unregister_udevice = udevman_unregister_udevice;
816  udevman->iface.get_udevice_by_UsbDevice = udevman_get_udevice_by_UsbDevice;
817  udevman->iface.get_udevice_by_ChannelID = udevman_get_udevice_by_ChannelID;
818  /* Extension */
819  udevman->iface.isAutoAdd = udevman_is_auto_add;
820  /* Basic state */
821  BASIC_STATE_FUNC_REGISTER(device_num, udevman);
822  BASIC_STATE_FUNC_REGISTER(next_device_id, udevman);
823 
824  /* control semaphore or mutex lock */
825  udevman->iface.loading_lock = udevman_loading_lock;
826  udevman->iface.loading_unlock = udevman_loading_unlock;
827  udevman->iface.initialize = udevman_initialize;
828  udevman->iface.listener_created_callback = udevman_listener_created_callback;
829 }
830 
831 static BOOL poll_libusb_events(UDEVMAN* udevman)
832 {
833  int rc = LIBUSB_SUCCESS;
834  struct timeval tv = { 0, 500 };
835  if (libusb_try_lock_events(udevman->context) == 0)
836  {
837  if (libusb_event_handling_ok(udevman->context))
838  {
839  rc = libusb_handle_events_locked(udevman->context, &tv);
840  if (rc != LIBUSB_SUCCESS)
841  WLog_WARN(TAG, "libusb_handle_events_locked %d", rc);
842  }
843  libusb_unlock_events(udevman->context);
844  }
845  else
846  {
847  libusb_lock_event_waiters(udevman->context);
848  if (libusb_event_handler_active(udevman->context))
849  {
850  rc = libusb_wait_for_event(udevman->context, &tv);
851  if (rc < LIBUSB_SUCCESS)
852  WLog_WARN(TAG, "libusb_wait_for_event %d", rc);
853  }
854  libusb_unlock_event_waiters(udevman->context);
855  }
856 
857  return rc > 0;
858 }
859 
860 static DWORD WINAPI poll_thread(LPVOID lpThreadParameter)
861 {
862  libusb_hotplug_callback_handle handle = 0;
863  UDEVMAN* udevman = (UDEVMAN*)lpThreadParameter;
864  BOOL hasHotplug = libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG);
865 
866  if (hasHotplug)
867  {
868  int rc = libusb_hotplug_register_callback(
869  udevman->context,
870  LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
871  LIBUSB_HOTPLUG_NO_FLAGS, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
872  LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, udevman, &handle);
873 
874  if (rc != LIBUSB_SUCCESS)
875  udevman->running = FALSE;
876  }
877  else
878  WLog_WARN(TAG, "Platform does not support libusb hotplug. USB devices plugged in later "
879  "will not be detected.");
880 
881  while (udevman->running)
882  {
883  poll_libusb_events(udevman);
884  }
885 
886  if (hasHotplug)
887  libusb_hotplug_deregister_callback(udevman->context, handle);
888 
889  /* Process remaining usb events */
890  while (poll_libusb_events(udevman))
891  ;
892 
893  ExitThread(0);
894  return 0;
895 }
896 
897 FREERDP_ENTRY_POINT(UINT VCAPITYPE libusb_freerdp_urbdrc_client_subsystem_entry(
899 {
900  wObject* obj = NULL;
901  UINT rc = 0;
902  UINT status = 0;
903  UDEVMAN* udevman = NULL;
904  const ADDIN_ARGV* args = pEntryPoints->args;
905  udevman = (PUDEVMAN)calloc(1, sizeof(UDEVMAN));
906 
907  if (!udevman)
908  goto fail;
909 
910  udevman->hotplug_vid_pids = ArrayList_New(TRUE);
911  if (!udevman->hotplug_vid_pids)
912  goto fail;
913  obj = ArrayList_Object(udevman->hotplug_vid_pids);
914  obj->fnObjectFree = free;
915  obj->fnObjectEquals = udevman_vid_pid_pair_equals;
916 
917  udevman->next_device_id = BASE_USBDEVICE_NUM;
918  udevman->iface.plugin = pEntryPoints->plugin;
919  rc = libusb_init(&udevman->context);
920 
921  if (rc != LIBUSB_SUCCESS)
922  goto fail;
923 
924 #ifdef _WIN32
925 #if LIBUSB_API_VERSION >= 0x01000106
926  /* Prefer usbDK backend on windows. Not supported on other platforms. */
927  rc = libusb_set_option(udevman->context, LIBUSB_OPTION_USE_USBDK);
928  switch (rc)
929  {
930  case LIBUSB_SUCCESS:
931  break;
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);
935  break;
936  default:
937  WLog_ERR(TAG, "LIBUSB_OPTION_USE_USBDK %s [%d]", libusb_strerror(rc), rc);
938  goto fail;
939  }
940 #endif
941 #endif
942 
943  udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
944  udevman->devman_loading = CreateMutexA(NULL, FALSE, "devman_loading");
945 
946  if (!udevman->devman_loading)
947  goto fail;
948 
949  /* load usb device service management */
950  udevman_load_interface(udevman);
951  status = urbdrc_udevman_parse_addin_args(udevman, args);
952 
953  if (status != CHANNEL_RC_OK)
954  goto fail;
955 
956  udevman->running = TRUE;
957  udevman->thread = CreateThread(NULL, 0, poll_thread, udevman, 0, NULL);
958 
959  if (!udevman->thread)
960  goto fail;
961 
962  if (!pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*)udevman))
963  goto fail;
964 
965  WLog_DBG(TAG, "UDEVMAN device registered.");
966  return 0;
967 fail:
968  udevman_free(&udevman->iface);
969  return ERROR_INTERNAL_ERROR;
970 }
Definition: urbdrc_main.h:71
This struct contains function pointer to initialize/free objects.
Definition: collections.h:57