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