Extend LIBUSB_API_VERSION check
[platform/upstream/freerdp.git] / channels / urbdrc / client / libusb / libusb_udevman.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Implementation
3  * RemoteFX USB Redirection
4  *
5  * Copyright 2012 Atrust corp.
6  * Copyright 2012 Alfred Liu <alfred.liu@atruscorp.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *     http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25
26 #include <libusb.h>
27 #include <winpr/crt.h>
28 #include <winpr/cmdline.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 #if !defined(LIBUSB_API_VERSION) || (LIBUSB_API_VERSION < 0x01000102)
38 #define LIBUSB_HOTPLUG_NO_FLAGS 0
39 #endif
40
41 #define BASIC_STATE_FUNC_DEFINED(_arg, _type)                   \
42         static _type udevman_get_##_arg(IUDEVMAN* idevman)          \
43         {                                                           \
44                 UDEVMAN* udevman = (UDEVMAN*)idevman;                   \
45                 return udevman->_arg;                                   \
46         }                                                           \
47         static void udevman_set_##_arg(IUDEVMAN* idevman, _type _t) \
48         {                                                           \
49                 UDEVMAN* udevman = (UDEVMAN*)idevman;                   \
50                 udevman->_arg = _t;                                     \
51         }
52
53 #define BASIC_STATE_FUNC_REGISTER(_arg, _man)    \
54         _man->iface.get_##_arg = udevman_get_##_arg; \
55         _man->iface.set_##_arg = udevman_set_##_arg
56
57 typedef struct _UDEVMAN UDEVMAN;
58
59 struct _UDEVMAN
60 {
61         IUDEVMAN iface;
62
63         IUDEVICE* idev; /* iterator device */
64         IUDEVICE* head; /* head device in linked list */
65         IUDEVICE* tail; /* tail device in linked list */
66
67         UINT32 defUsbDevice;
68         UINT16 flags;
69         UINT32 device_num;
70         int sem_timeout;
71
72         HANDLE devman_loading;
73         libusb_context* context;
74         libusb_hotplug_callback_handle handle;
75         HANDLE thread;
76         BOOL running;
77 };
78 typedef UDEVMAN* PUDEVMAN;
79
80 static BOOL poll_libusb_events(UDEVMAN* udevman);
81
82 static void udevman_rewind(IUDEVMAN* idevman)
83 {
84         UDEVMAN* udevman = (UDEVMAN*)idevman;
85         udevman->idev = udevman->head;
86 }
87
88 static BOOL udevman_has_next(IUDEVMAN* idevman)
89 {
90         UDEVMAN* udevman = (UDEVMAN*)idevman;
91
92         if (!udevman || !udevman->idev)
93                 return FALSE;
94         else
95                 return TRUE;
96 }
97
98 static IUDEVICE* udevman_get_next(IUDEVMAN* idevman)
99 {
100         UDEVMAN* udevman = (UDEVMAN*)idevman;
101         IUDEVICE* pdev;
102         pdev = udevman->idev;
103         udevman->idev = (IUDEVICE*)((UDEVICE*)udevman->idev)->next;
104         return pdev;
105 }
106
107 static IUDEVICE* udevman_get_udevice_by_addr(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number)
108 {
109         IUDEVICE* dev = NULL;
110
111         if (!idevman)
112                 return NULL;
113
114         idevman->loading_lock(idevman);
115         idevman->rewind(idevman);
116
117         while (idevman->has_next(idevman))
118         {
119                 IUDEVICE* pdev = idevman->get_next(idevman);
120
121                 if ((pdev->get_bus_number(pdev) == bus_number) &&
122                     (pdev->get_dev_number(pdev) == dev_number))
123                 {
124                         dev = pdev;
125                         break;
126                 }
127         }
128
129         idevman->loading_unlock(idevman);
130         return dev;
131 }
132
133 static size_t udevman_register_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number,
134                                        UINT32 UsbDevice, UINT16 idVendor, UINT16 idProduct,
135                                        int flag)
136 {
137         UDEVMAN* udevman = (UDEVMAN*)idevman;
138         IUDEVICE* pdev = NULL;
139         IUDEVICE** devArray;
140         URBDRC_PLUGIN* urbdrc;
141         size_t i, num, addnum = 0;
142
143         if (!idevman || !idevman->plugin)
144                 return 0;
145
146         urbdrc = (URBDRC_PLUGIN*)idevman->plugin;
147         pdev = (IUDEVICE*)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
148
149         if (pdev != NULL)
150                 return 0;
151
152         if (flag == UDEVMAN_FLAG_ADD_BY_ADDR)
153         {
154                 IUDEVICE* tdev = udev_new_by_addr(urbdrc, bus_number, dev_number);
155
156                 if (tdev == NULL)
157                         return 0;
158
159                 tdev->set_UsbDevice(tdev, UsbDevice);
160                 idevman->loading_lock(idevman);
161
162                 if (udevman->head == NULL)
163                 {
164                         /* linked list is empty */
165                         udevman->head = tdev;
166                         udevman->tail = tdev;
167                 }
168                 else
169                 {
170                         /* append device to the end of the linked list */
171                         udevman->tail->set_p_next(udevman->tail, tdev);
172                         tdev->set_p_prev(tdev, udevman->tail);
173                         udevman->tail = tdev;
174                 }
175
176                 udevman->device_num += 1;
177                 idevman->loading_unlock(idevman);
178         }
179         else if (flag == UDEVMAN_FLAG_ADD_BY_VID_PID)
180         {
181                 addnum = 0;
182                 /* register all device that match pid vid */
183                 num = udev_new_by_id(urbdrc, idVendor, idProduct, &devArray);
184
185                 for (i = 0; i < num; i++)
186                 {
187                         IUDEVICE* tdev = devArray[i];
188
189                         if (udevman_get_udevice_by_addr(idevman, tdev->get_bus_number(tdev),
190                                                         tdev->get_dev_number(tdev)) != NULL)
191                         {
192                                 tdev->free(tdev);
193                                 devArray[i] = NULL;
194                                 continue;
195                         }
196
197                         tdev->set_UsbDevice(tdev, UsbDevice);
198                         idevman->loading_lock(idevman);
199
200                         if (udevman->head == NULL)
201                         {
202                                 /* linked list is empty */
203                                 udevman->head = tdev;
204                                 udevman->tail = tdev;
205                         }
206                         else
207                         {
208                                 /* append device to the end of the linked list */
209                                 udevman->tail->set_p_next(udevman->tail, tdev);
210                                 tdev->set_p_prev(tdev, udevman->tail);
211                                 udevman->tail = tdev;
212                         }
213
214                         udevman->device_num += 1;
215                         idevman->loading_unlock(idevman);
216                         addnum++;
217                 }
218
219                 free(devArray);
220                 return addnum;
221         }
222         else
223         {
224                 WLog_Print(urbdrc->log, WLOG_ERROR, "udevman_register_udevice: Invalid flag=%08 " PRIx32,
225                            flag);
226                 return 0;
227         }
228
229         return 1;
230 }
231
232 static BOOL udevman_unregister_udevice(IUDEVMAN* idevman, BYTE bus_number, BYTE dev_number)
233 {
234         UDEVMAN* udevman = (UDEVMAN*)idevman;
235         UDEVICE* pdev;
236         UDEVICE* dev = (UDEVICE*)udevman_get_udevice_by_addr(idevman, bus_number, dev_number);
237
238         if (!dev || !idevman)
239                 return FALSE;
240
241         idevman->loading_lock(idevman);
242         idevman->rewind(idevman);
243
244         while (idevman->has_next(idevman))
245         {
246                 pdev = (UDEVICE*)idevman->get_next(idevman);
247
248                 if (pdev == dev) /* device exists */
249                 {
250                         /* set previous device to point to next device */
251                         if (dev->prev != NULL)
252                         {
253                                 /* unregistered device is not the head */
254                                 pdev = dev->prev;
255                                 pdev->next = dev->next;
256                         }
257                         else
258                         {
259                                 /* unregistered device is the head, update head */
260                                 udevman->head = (IUDEVICE*)dev->next;
261                         }
262
263                         /* set next device to point to previous device */
264
265                         if (dev->next != NULL)
266                         {
267                                 /* unregistered device is not the tail */
268                                 pdev = (UDEVICE*)dev->next;
269                                 pdev->prev = dev->prev;
270                         }
271                         else
272                         {
273                                 /* unregistered device is the tail, update tail */
274                                 udevman->tail = (IUDEVICE*)dev->prev;
275                         }
276
277                         udevman->device_num--;
278                         break;
279                 }
280         }
281
282         idevman->loading_unlock(idevman);
283
284         if (dev)
285         {
286                 dev->iface.free(&dev->iface);
287                 return TRUE; /* unregistration successful */
288         }
289
290         /* if we reach this point, the device wasn't found */
291         return FALSE;
292 }
293
294 static BOOL udevman_cancel_all_device_requests(IUDEVMAN* idevman)
295 {
296         UDEVMAN* udevman = (UDEVMAN*)idevman;
297
298         if (!idevman)
299                 return FALSE;
300
301         idevman->loading_lock(idevman);
302         idevman->rewind(idevman);
303
304         while (idevman->has_next(idevman))
305         {
306                 UDEVICE* dev = (UDEVICE*)idevman->get_next(idevman);
307
308                 if (!dev)
309                         continue;
310                 dev->iface.cancel_all_transfer_request(&dev->iface);
311         }
312
313         idevman->loading_unlock(idevman);
314
315         return TRUE;
316 }
317
318 static BOOL udevman_unregister_all_udevices(IUDEVMAN* idevman)
319 {
320         UDEVMAN* udevman = (UDEVMAN*)idevman;
321
322         if (!idevman)
323                 return FALSE;
324
325         idevman->loading_lock(idevman);
326         idevman->rewind(idevman);
327
328         while (idevman->has_next(idevman))
329         {
330                 UDEVICE* dev = (UDEVICE*)idevman->get_next(idevman);
331
332                 if (!dev)
333                         continue;
334
335                 /* set previous device to point to next device */
336                 if (dev->prev != NULL)
337                 {
338                         /* unregistered device is not the head */
339                         UDEVICE* pdev = dev->prev;
340                         pdev->next = dev->next;
341                 }
342                 else
343                 {
344                         /* unregistered device is the head, update head */
345                         udevman->head = (IUDEVICE*)dev->next;
346                 }
347
348                 /* set next device to point to previous device */
349
350                 if (dev->next != NULL)
351                 {
352                         /* unregistered device is not the tail */
353                         UDEVICE* pdev = (UDEVICE*)dev->next;
354                         pdev->prev = dev->prev;
355                 }
356                 else
357                 {
358                         /* unregistered device is the tail, update tail */
359                         udevman->tail = (IUDEVICE*)dev->prev;
360                 }
361
362                 dev->iface.free(&dev->iface);
363                 udevman->device_num--;
364         }
365
366         idevman->loading_unlock(idevman);
367
368         return TRUE;
369 }
370
371 static BOOL udevman_parse_device_addr(const char* str, size_t maxLen, UINT16* id1, UINT16* id2,
372                                       char sign)
373 {
374         unsigned long rc;
375         char s1[8] = { 0 };
376         char* s2;
377         size_t len = strnlen(str, maxLen);
378         size_t cpLen;
379         s2 = (strchr(str, sign)) + 1;
380
381         if (!s2)
382                 return FALSE;
383
384         cpLen = len - (strnlen(s2, len) + 1);
385
386         if (cpLen >= sizeof(s1))
387                 cpLen = sizeof(s1) - 1;
388
389         strncpy(s1, str, cpLen);
390         rc = strtoul(s1, NULL, 16);
391
392         if ((rc > UINT16_MAX) || (errno != 0))
393                 return FALSE;
394
395         *id1 = rc;
396         rc = strtoul(s2, NULL, 16);
397
398         if ((rc > UINT16_MAX) || (errno != 0))
399                 return FALSE;
400
401         *id2 = rc;
402         return TRUE;
403 }
404
405 static BOOL udevman_parse_device_pid_vid(const char* str, size_t maxLen, UINT16* id1, UINT16* id2,
406                                          char sign)
407 {
408         unsigned long rc;
409         char s1[8] = { 0 };
410         char* s2;
411         size_t len = strnlen(str, maxLen);
412         size_t cpLen;
413         s2 = (strchr(str, sign)) + 1;
414
415         if (!s2)
416                 return FALSE;
417
418         cpLen = len - (strnlen(s2, len) + 1);
419
420         if (cpLen >= sizeof(s1))
421                 cpLen = sizeof(s1) - 1;
422
423         strncpy(s1, str, cpLen);
424         errno = 0;
425         rc = strtoul(s1, NULL, 16);
426
427         if ((rc > UINT16_MAX) || (errno != 0))
428                 return FALSE;
429
430         *id1 = rc;
431         rc = strtoul(s2, NULL, 16);
432
433         if ((rc > UINT16_MAX) || (errno != 0))
434                 return FALSE;
435
436         *id2 = rc;
437         return TRUE;
438 }
439
440 static int udevman_check_device_exist_by_id(IUDEVMAN* idevman, UINT16 idVendor, UINT16 idProduct)
441 {
442         if (libusb_open_device_with_vid_pid(NULL, idVendor, idProduct))
443                 return 1;
444
445         return 0;
446 }
447
448 static int udevman_is_auto_add(IUDEVMAN* idevman)
449 {
450         UDEVMAN* udevman = (UDEVMAN*)idevman;
451         return (udevman->flags & UDEVMAN_FLAG_ADD_BY_AUTO) ? 1 : 0;
452 }
453
454 static IUDEVICE* udevman_get_udevice_by_UsbDevice(IUDEVMAN* idevman, UINT32 UsbDevice)
455 {
456         UDEVICE* pdev;
457         URBDRC_PLUGIN* urbdrc;
458
459         if (!idevman || !idevman->plugin)
460                 return NULL;
461
462         /* Mask highest 2 bits, must be ignored */
463         UsbDevice = UsbDevice & INTERFACE_ID_MASK;
464         urbdrc = (URBDRC_PLUGIN*)idevman->plugin;
465         idevman->loading_lock(idevman);
466         idevman->rewind(idevman);
467
468         while (idevman->has_next(idevman))
469         {
470                 pdev = (UDEVICE*)idevman->get_next(idevman);
471
472                 if (pdev->UsbDevice == UsbDevice)
473                 {
474                         idevman->loading_unlock(idevman);
475                         return (IUDEVICE*)pdev;
476                 }
477         }
478
479         idevman->loading_unlock(idevman);
480         WLog_Print(urbdrc->log, WLOG_WARN, "Failed to find a USB device mapped to deviceId=%08" PRIx32,
481                    UsbDevice);
482         return NULL;
483 }
484
485 static void udevman_loading_lock(IUDEVMAN* idevman)
486 {
487         UDEVMAN* udevman = (UDEVMAN*)idevman;
488         WaitForSingleObject(udevman->devman_loading, INFINITE);
489 }
490
491 static void udevman_loading_unlock(IUDEVMAN* idevman)
492 {
493         UDEVMAN* udevman = (UDEVMAN*)idevman;
494         ReleaseMutex(udevman->devman_loading);
495 }
496
497 BASIC_STATE_FUNC_DEFINED(defUsbDevice, UINT32)
498 BASIC_STATE_FUNC_DEFINED(device_num, UINT32)
499 BASIC_STATE_FUNC_DEFINED(sem_timeout, int)
500
501 static void udevman_free(IUDEVMAN* idevman)
502 {
503         UDEVMAN* udevman = (UDEVMAN*)idevman;
504
505         if (!udevman)
506                 return;
507
508         libusb_hotplug_deregister_callback(udevman->context, udevman->handle);
509
510         udevman->running = FALSE;
511         WaitForSingleObject(udevman->thread, INFINITE);
512
513         /* Process remaining usb events */
514         while (poll_libusb_events(udevman))
515                 ;
516
517         udevman_unregister_all_udevices(idevman);
518         CloseHandle(udevman->devman_loading);
519         CloseHandle(udevman->thread);
520         libusb_exit(udevman->context);
521
522         free(udevman);
523 }
524
525 static int hotplug_callback(struct libusb_context* ctx, struct libusb_device* dev,
526                             libusb_hotplug_event event, void* user_data)
527 {
528         int rc;
529         struct libusb_device_descriptor desc;
530         IUDEVMAN* idevman = (IUDEVMAN*)user_data;
531         const uint8_t bus = libusb_get_bus_number(dev);
532         const uint8_t addr = libusb_get_device_address(dev);
533         rc = libusb_get_device_descriptor(dev, &desc);
534
535         if (rc != LIBUSB_SUCCESS)
536                 return rc;
537
538         switch (event)
539         {
540                 case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
541                         add_device(idevman, bus, addr, desc.iManufacturer, desc.iProduct);
542                         break;
543
544                 case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
545                         del_device(idevman, bus, addr, desc.iManufacturer, desc.iProduct);
546                         break;
547
548                 default:
549                         break;
550         }
551
552         return 0;
553 }
554
555 static BOOL udevman_initialize(IUDEVMAN* idevman, UINT32 channelId)
556 {
557         UDEVMAN* udevman = (UDEVMAN*)idevman;
558
559         if (!udevman)
560                 return FALSE;
561
562         idevman->controlChannelId = channelId;
563         return TRUE;
564 }
565
566 static void udevman_load_interface(UDEVMAN* udevman)
567 {
568         /* standard */
569         udevman->iface.free = udevman_free;
570         /* manage devices */
571         udevman->iface.rewind = udevman_rewind;
572         udevman->iface.get_next = udevman_get_next;
573         udevman->iface.has_next = udevman_has_next;
574         udevman->iface.register_udevice = udevman_register_udevice;
575         udevman->iface.unregister_udevice = udevman_unregister_udevice;
576         udevman->iface.get_udevice_by_UsbDevice = udevman_get_udevice_by_UsbDevice;
577         /* Extension */
578         udevman->iface.check_device_exist_by_id = udevman_check_device_exist_by_id;
579         udevman->iface.isAutoAdd = udevman_is_auto_add;
580         /* Basic state */
581         BASIC_STATE_FUNC_REGISTER(defUsbDevice, udevman);
582         BASIC_STATE_FUNC_REGISTER(device_num, udevman);
583         BASIC_STATE_FUNC_REGISTER(sem_timeout, udevman);
584         /* control semaphore or mutex lock */
585         udevman->iface.loading_lock = udevman_loading_lock;
586         udevman->iface.loading_unlock = udevman_loading_unlock;
587         udevman->iface.initialize = udevman_initialize;
588 }
589
590 static BOOL urbdrc_udevman_register_devices(UDEVMAN* udevman, const char* devices)
591 {
592         BOOL rc = FALSE;
593         char* token;
594         int success = 0;
595         char* tmp;
596         char hardware_id[16];
597         const char* default_devices = "id";
598         UINT32 UsbDevice = BASE_USBDEVICE_NUM;
599
600         if (!devices)
601                 tmp = _strdup(default_devices);
602         else
603                 tmp = _strdup(devices);
604
605         /* register all usb devices */
606         token = strtok(tmp, "#");
607
608         while (token)
609         {
610                 strcpy(hardware_id, token);
611                 token = strtok(NULL, "#");
612
613                 if (udevman->flags & UDEVMAN_FLAG_ADD_BY_VID_PID)
614                 {
615                         UINT16 idVendor, idProduct;
616
617                         if (!udevman_parse_device_pid_vid(hardware_id, sizeof(hardware_id), &idVendor,
618                                                           &idProduct, ':'))
619                                 goto fail;
620
621                         success = udevman->iface.register_udevice((IUDEVMAN*)udevman, 0, 0, UsbDevice, idVendor,
622                                                                   idProduct, UDEVMAN_FLAG_ADD_BY_VID_PID);
623                 }
624                 else if (udevman->flags & UDEVMAN_FLAG_ADD_BY_ADDR)
625                 {
626                         UINT16 bus_number, dev_number;
627
628                         if (!udevman_parse_device_addr(hardware_id, sizeof(hardware_id), &bus_number,
629                                                        &dev_number, ':'))
630                                 goto fail;
631
632                         success = udevman->iface.register_udevice((IUDEVMAN*)udevman, bus_number, dev_number,
633                                                                   UsbDevice, 0, 0, UDEVMAN_FLAG_ADD_BY_ADDR);
634                 }
635
636                 if (success)
637                         UsbDevice++;
638         }
639
640         udevman->defUsbDevice = UsbDevice;
641         rc = TRUE;
642 fail:
643         free(tmp);
644         return rc;
645 }
646
647 static UINT urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
648 {
649         int status;
650         DWORD flags;
651         LPSTR devices = NULL;
652         const UINT16 mask = UDEVMAN_FLAG_ADD_BY_VID_PID | UDEVMAN_FLAG_ADD_BY_ADDR;
653         COMMAND_LINE_ARGUMENT_A* arg;
654         COMMAND_LINE_ARGUMENT_A urbdrc_udevman_args[] = {
655                 { "dbg", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "debug" },
656                 { "dev", COMMAND_LINE_VALUE_REQUIRED, "<devices>", NULL, NULL, -1, NULL, "device list" },
657                 { "id", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL,
658                   "FLAG_ADD_BY_VID_PID" },
659                 { "addr", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "FLAG_ADD_BY_ADDR" },
660                 { "auto", COMMAND_LINE_VALUE_FLAG, "", NULL, BoolValueFalse, -1, NULL, "FLAG_ADD_BY_AUTO" },
661                 { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
662         };
663
664         flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
665         status = CommandLineParseArgumentsA(args->argc, args->argv, urbdrc_udevman_args, flags, udevman,
666                                             NULL, NULL);
667
668         if (status != CHANNEL_RC_OK)
669                 return status;
670
671         arg = urbdrc_udevman_args;
672
673         do
674         {
675                 if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
676                         continue;
677
678                 CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dbg")
679                 {
680                         WLog_SetLogLevel(WLog_Get(TAG), WLOG_TRACE);
681                 }
682                 CommandLineSwitchCase(arg, "dev")
683                 {
684                         devices = arg->Value;
685                 }
686                 CommandLineSwitchCase(arg, "id")
687                 {
688                         udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
689                 }
690                 CommandLineSwitchCase(arg, "addr")
691                 {
692                         udevman->flags = UDEVMAN_FLAG_ADD_BY_ADDR;
693                 }
694                 CommandLineSwitchCase(arg, "auto")
695                 {
696                         udevman->flags |= UDEVMAN_FLAG_ADD_BY_AUTO;
697                 }
698                 CommandLineSwitchDefault(arg)
699                 {
700                 }
701                 CommandLineSwitchEnd(arg)
702         } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
703
704         /* Can not add devices by address and VID/PID */
705         if ((udevman->flags & mask) == mask)
706                 return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
707
708         /* Add listed devices after we know the format of addressing */
709         if (devices)
710         {
711                 if (!urbdrc_udevman_register_devices(udevman, devices))
712                         return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
713         }
714
715         return CHANNEL_RC_OK;
716 }
717
718 static BOOL poll_libusb_events(UDEVMAN* udevman)
719 {
720         int rc = LIBUSB_SUCCESS;
721         struct timeval tv = { 0, 500 };
722         if (libusb_try_lock_events(udevman->context))
723         {
724                 if (libusb_event_handling_ok(udevman->context))
725                 {
726                         rc = libusb_handle_events_locked(udevman->context, &tv);
727                         if (rc != LIBUSB_SUCCESS)
728                                 WLog_WARN(TAG, "libusb_handle_events_locked %d", rc);
729                 }
730                 libusb_unlock_events(udevman->context);
731         }
732         else
733         {
734                 libusb_lock_event_waiters(udevman->context);
735                 if (libusb_event_handler_active(udevman->context))
736                 {
737                         rc = libusb_wait_for_event(udevman->context, &tv);
738                         if (rc < LIBUSB_SUCCESS)
739                                 WLog_WARN(TAG, "libusb_wait_for_event %d", rc);
740                 }
741                 libusb_unlock_event_waiters(udevman->context);
742         }
743
744         return rc > 0;
745 }
746
747 static DWORD poll_thread(LPVOID lpThreadParameter)
748 {
749         UDEVMAN* udevman = (UDEVMAN*)lpThreadParameter;
750
751         while (udevman->running)
752         {
753                 poll_libusb_events(udevman);
754         }
755
756         return 0;
757 }
758
759 #ifdef BUILTIN_CHANNELS
760 #define freerdp_urbdrc_client_subsystem_entry libusb_freerdp_urbdrc_client_subsystem_entry
761 #else
762 #define freerdp_urbdrc_client_subsystem_entry FREERDP_API freerdp_urbdrc_client_subsystem_entry
763 #endif
764 int freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)
765 {
766         int rc;
767         UINT status;
768         UDEVMAN* udevman;
769         ADDIN_ARGV* args = pEntryPoints->args;
770         udevman = (PUDEVMAN)calloc(1, sizeof(UDEVMAN));
771
772         if (!udevman)
773                 goto fail;
774
775         udevman->iface.plugin = pEntryPoints->plugin;
776         rc = libusb_init(&udevman->context);
777
778         if (rc != LIBUSB_SUCCESS)
779                 goto fail;
780
781         udevman->flags = UDEVMAN_FLAG_ADD_BY_VID_PID;
782         udevman->devman_loading = CreateMutexA(NULL, FALSE, "devman_loading");
783
784         if (!udevman->devman_loading)
785                 goto fail;
786
787         /* load usb device service management */
788         udevman_load_interface(udevman);
789         status = urbdrc_udevman_parse_addin_args(udevman, args);
790
791         if (status != CHANNEL_RC_OK)
792                 goto fail;
793
794         udevman->running = TRUE;
795         udevman->thread = CreateThread(NULL, 0, poll_thread, udevman, 0, NULL);
796
797         if (!udevman->thread)
798                 goto fail;
799
800         rc = libusb_hotplug_register_callback(
801             udevman->context, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT,
802             LIBUSB_HOTPLUG_NO_FLAGS, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
803             LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, udevman, &udevman->handle);
804
805         if (rc != LIBUSB_SUCCESS)
806                 goto fail;
807
808         if (!pEntryPoints->pRegisterUDEVMAN(pEntryPoints->plugin, (IUDEVMAN*)udevman))
809                 goto fail;
810
811         WLog_DBG(TAG, "UDEVMAN device registered.");
812         return 0;
813 fail:
814         udevman_free(&udevman->iface);
815         return -1;
816 }