VirtualBox

source: vbox/trunk/src/VBox/RDP/client/vrdp/rdpusb.c@ 7918

最後變更 在這個檔案從7918是 7826,由 vboxsync 提交於 17 年 前

Export modified rdesktop version including USB support to OSE. It's GPL anyway.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 17.4 KB
 
1/** @file
2 *
3 * Remote Desktop Protocol client:
4 * USB Channel Process Functions
5 *
6 */
7
8/*
9 * Copyright (C) 2006-2007 innotek GmbH
10 *
11 * innotek GmbH confidential
12 * All rights reserved
13 */
14
15#include "../rdesktop.h"
16
17#include <unistd.h>
18#include <ctype.h>
19#include <fcntl.h>
20
21#include "vrdpusb.h"
22
23#define RDPUSB_REQ_OPEN (0)
24#define RDPUSB_REQ_CLOSE (1)
25#define RDPUSB_REQ_RESET (2)
26#define RDPUSB_REQ_SET_CONFIG (3)
27#define RDPUSB_REQ_CLAIM_INTERFACE (4)
28#define RDPUSB_REQ_RELEASE_INTERFACE (5)
29#define RDPUSB_REQ_INTERFACE_SETTING (6)
30#define RDPUSB_REQ_QUEUE_URB (7)
31#define RDPUSB_REQ_REAP_URB (8)
32#define RDPUSB_REQ_CLEAR_HALTED_EP (9)
33#define RDPUSB_REQ_CANCEL_URB (10)
34#define RDPUSB_REQ_DEVICE_LIST (11)
35#define RDPUSB_REQ_NEGOTIATE (12)
36
37static VCHANNEL *rdpusb_channel;
38
39#define PROC_BUS_USB "/proc/bus/usb"
40
41/* A device list entry */
42#pragma pack (1)
43typedef struct _DevListEntry
44{
45 uint16_t oNext; /* Offset of the next structure. 0 if last. */
46 uint32_t id; /* Identifier of the device assigned by the client. */
47 uint16_t bcdUSB; /* USB verion number. */
48 uint8_t bDeviceClass; /* Device class. */
49 uint8_t bDeviceSubClass; /* Device subclass. */
50 uint8_t bDeviceProtocol; /* Device protocol. */
51 uint16_t idVendor; /* Vendor id. */
52 uint16_t idProduct; /* Product id. */
53 uint16_t bcdRev; /* Revision. */
54 uint16_t oManufacturer; /* Offset of manufacturer string. */
55 uint16_t oProduct; /* Offset of product string. */
56 uint16_t oSerialNumber; /* Offset of serial string. */
57 uint16_t idPort; /* Physical USB port the device is connected to. */
58} DevListEntry;
59#pragma pack ()
60
61static uint16 getBcd (const char *str, const char *prefix)
62{
63 char *p = strstr (str, prefix);
64 if (p)
65 {
66 uint16 h, l;
67
68 p += strlen (prefix);
69
70 while (*p == ' ') p++; // skiping spaces
71
72 h = (uint16)strtoul (p, &p, 10) & 0xFF;
73
74 if (*p == '.')
75 {
76 l = (uint16)strtoul (p + 1, NULL, 10) & 0xFF;
77
78 return (h << 8) + l;
79 }
80 }
81
82 Log(("Could not get BCD '%s' in line [%s]\n", prefix, str));
83
84 return 0;
85}
86
87static uint8 getU8 (const char *str, const char *prefix)
88{
89 char *p = strstr (str, prefix);
90 if (p)
91 {
92 p += strlen (prefix);
93 while (*p == ' ') p++; // skiping spaces
94 return ((uint8)strtoul(p, NULL, 10) & 0xFF);
95 }
96
97 Log(("Could not get U8 '%s' in line [%s]\n", prefix, str));
98
99 return 0;
100}
101
102static uint16 getU16 (const char *str, const char *prefix)
103{
104 char *p = strstr (str, prefix);
105 if (p)
106 {
107 uint16 tmp16;
108 p += strlen (prefix);
109 while (*p == ' ') p++; // skiping spaces
110 tmp16 = (uint16)strtoul (p, NULL, 16);
111 return (tmp16);
112 }
113
114 Log(("Could not get U16 '%s' in line [%s]\n", prefix, str));
115
116 return 0;
117}
118
119static char *getString (const char *str, const char *prefix)
120{
121 char *p = strstr (str, prefix);
122 if (p)
123 {
124 return (char *)p + strlen (prefix);
125 }
126
127 return 0;
128}
129
130
131static void *build_device_list (int *plen)
132{
133 Log(("RDPUSB build_device_list"));
134
135 uint8 tmp8;
136
137 uint32 size = 0;
138 uint32 len = 0;
139 uint32 lastlen = 0;
140 uint8 *buffer = NULL;
141
142 char szLine[1024];
143 char *p;
144
145 DevListEntry *e = NULL;
146
147 FILE *f = fopen (PROC_BUS_USB "/devices", "r");
148
149 if (f != NULL)
150 {
151 while (fgets (szLine, sizeof (szLine), f))
152 {
153 p = strchr (szLine, '\n');
154 if (p) *p = 0;
155
156 p = &szLine[0];
157
158// Log(("%s\n", szLine));
159
160 switch (*p)
161 {
162 case 'T':
163 {
164 /* A new device, allocate memory. */
165 if (size - len < sizeof (DevListEntry))
166 {
167 buffer = (uint8*)xrealloc (buffer, size + sizeof (DevListEntry));
168 size += sizeof (DevListEntry);
169 }
170
171 if (len > 0)
172 {
173 e = (DevListEntry *)&buffer[lastlen];
174
175 char path[128];
176
177 sprintf (path, PROC_BUS_USB "/%03d/%03d", (e->id>>8) & 0xFF, e->id & 0xFF);
178
179 Log(("%s: id = %X, class = %d access = %d\n", path, e->id, e->bDeviceClass, access (path, R_OK | W_OK)));
180
181 if (e->id != 0 && e->bDeviceClass != 9 && access (path, R_OK | W_OK) == 0) // skip hubs as well
182 {
183 Log(("Added device vendor %04X, product %04X\n", e->idVendor, e->idProduct));
184 e->oNext = len - lastlen;
185 }
186 else
187 {
188 /* The entry was not filled. Reuse.*/
189 len = lastlen;
190 }
191 }
192
193 lastlen = len;
194
195 e = (DevListEntry *)&buffer[lastlen];
196 memset (e, 0, sizeof (DevListEntry));
197
198 len += sizeof (DevListEntry);
199
200 // T: Bus=03 Lev=02 Prnt=36 Port=01 Cnt=02 Dev#= 38 Spd=12 MxCh= 0
201 /* Get bus and dev#. */
202 tmp8 = getU8 (szLine, "Bus=");
203 if (!tmp8)
204 {
205 e->id = 0;
206 }
207 else
208 {
209 e->idPort &= 0x00FF;
210 e->idPort |= (uint16)tmp8 << 8;
211 e->id &= 0x00FF;
212 e->id |= (uint16)tmp8 << 8;
213 }
214
215 if (e)
216 {
217 tmp8 = getU8 (szLine, "Dev#=");
218 if (!tmp8)
219 {
220 e->id = 0;
221 }
222 else
223 {
224 e->id &= 0xFF00;
225 e->id |= tmp8;
226 }
227
228 if (e->id != 0)
229 {
230 e->idPort &= 0xFF00;
231 e->idPort |= getU8 (szLine, "Port=");
232 }
233 }
234 } break;
235 case 'D':
236 {
237 // D: Ver= 1.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
238 if (e && e->id)
239 {
240 e->bcdUSB = getBcd (szLine, "Ver=");
241 e->bDeviceClass = getU8 (szLine, "Cls=");
242 e->bDeviceSubClass = getU8 (szLine, "Sub=");
243 e->bDeviceProtocol = getU8 (szLine, "Prot=");
244 }
245 } break;
246 case 'P':
247 {
248 // P: Vendor=0483 ProdID=2016 Rev= 0.01
249 if (e && e->id)
250 {
251 e->idVendor = getU16 (szLine, "Vendor=");
252 e->idProduct = getU16 (szLine, "ProdID=");
253 e->bcdRev = getBcd (szLine, "Rev=");
254 }
255
256 } break;
257 case 'S':
258 {
259 if (e && e->id)
260 {
261 // S: Manufacturer=STMicroelectronics
262 uint16 offset = len - lastlen;
263 uint16 offset_addr = 0;
264
265 char *s = getString (szLine, "Manufacturer=");
266 if (s)
267 {
268 offset_addr = (uint8 *)&e->oManufacturer - (uint8 *)e;
269 }
270 else
271 {
272 s = getString (szLine, "Product=");
273
274 if (s)
275 {
276 offset_addr = (uint8 *)&e->oProduct - (uint8 *)e;
277 }
278 else
279 {
280 s = getString (szLine, "SerialNumber=");
281
282 if (s)
283 {
284 offset_addr = (uint8 *)&e->oSerialNumber - (uint8 *)e;
285 }
286 }
287 }
288
289 if (s)
290 {
291 int l = strlen (s) + 1;
292
293 if (l > 1)
294 {
295 if (size - len < l)
296 {
297 buffer = (uint8*)xrealloc (buffer, size + l);
298 size += l;
299 e = (DevListEntry *)&buffer[lastlen];
300 }
301
302 memcpy (&buffer[len], s, l);
303 len += l;
304
305 *(uint16 *)((uint8 *)e + offset_addr) = offset;
306 }
307 else
308 {
309 *(uint16 *)((uint8 *)e + offset_addr) = 0;
310 }
311 }
312 }
313 } break;
314 }
315 }
316
317 if (len > 0)
318 {
319 Log(("Finalising list\n"));
320#ifdef RDPUSB_DEBUG
321 hexdump(buffer, lastlen);
322#endif
323
324 e = (DevListEntry *)&buffer[lastlen];
325
326 char path[128];
327
328 sprintf (path, PROC_BUS_USB "/%03d/%03d", (e->id>>8) & 0xFF, e->id & 0xFF);
329
330 if (e->id != 0 && e->bDeviceClass != 9 && access (path, R_OK | W_OK) == 0) // skip hubs as well
331 {
332 Log(("Added device vendor %04X, product %04X\n", e->idVendor, e->idProduct));
333 e->oNext = len - lastlen;
334 }
335 else
336 {
337 /* The entry was not filled. Reuse.*/
338 len = lastlen;
339 }
340
341 lastlen = len;
342
343 if (size - len < 2)
344 {
345 buffer = (uint8*)xrealloc (buffer, size + 2);
346 size += 2;
347 }
348
349 e = (DevListEntry *)&buffer[lastlen];
350 e->oNext = 0;
351 lastlen += 2;
352 }
353
354 fclose (f);
355 }
356
357 *plen = lastlen;
358 return buffer;
359}
360
361static STREAM
362rdpusb_init_packet(uint32 len, uint8 code)
363{
364 STREAM s;
365
366 s = channel_init(rdpusb_channel, len + 5);
367 out_uint32_le (s, len + sizeof (code)); /* The length of data after the 'len' field. */
368 out_uint8(s, code);
369 return s;
370}
371
372static void
373rdpusb_send(STREAM s)
374{
375#ifdef RDPUSB_DEBUG
376 Log(("RDPUSB send:\n"));
377 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
378#endif
379
380 channel_send(s, rdpusb_channel);
381}
382
383static void
384rdpusb_send_reply (uint8_t code, uint8_t status, uint32_t devid)
385{
386 STREAM s = rdpusb_init_packet(1, code);
387 out_uint8(s, status);
388 out_uint32_le(s, devid);
389 s_mark_end(s);
390 rdpusb_send(s);
391}
392
393static void
394rdpusb_send_access_denied (uint8_t code, uint32_t devid)
395{
396 rdpusb_send_reply (code, VRDP_USB_STATUS_ACCESS_DENIED, devid);
397}
398
399static inline int
400vrdp_usb_status (int rc, VUSBDEV *pdev)
401{
402 if (!rc || pdev->request_detach)
403 {
404 return VRDP_USB_STATUS_DEVICE_REMOVED;
405 }
406
407 return VRDP_USB_STATUS_SUCCESS;
408}
409
410static struct usb_proxy *g_proxies = NULL;
411
412static struct usb_proxy *
413devid2proxy (uint32_t devid)
414{
415 struct usb_proxy *proxy = g_proxies;
416
417 while (proxy && proxy->devid != devid)
418 {
419 proxy = proxy->next;
420 }
421
422 return proxy;
423}
424
425static void
426rdpusb_reap_urbs (void)
427{
428 STREAM s;
429
430 PVUSBURB pUrb = NULL;
431
432 struct usb_proxy *proxy = g_proxies;
433
434 while (proxy)
435 {
436 pUrb = op_usbproxy_back_reap_urb(proxy, 0);
437
438 if (pUrb)
439 {
440 int datalen = 0;
441
442 Log(("RDPUSB: rdpusb_reap_urbs: cbData = %d, enmStatus = %d\n", pUrb->cbData, pUrb->enmStatus));
443
444 if (pUrb->enmDir == VUSB_DIRECTION_IN)
445 {
446 datalen = pUrb->cbData;
447 }
448
449 s = rdpusb_init_packet(14 + datalen, RDPUSB_REQ_REAP_URB);
450 out_uint32_le(s, proxy->devid);
451 out_uint8(s, VRDP_USB_REAP_FLAG_LAST);
452 out_uint8(s, pUrb->enmStatus);
453 out_uint32_le(s, pUrb->handle);
454 out_uint32_le(s, pUrb->cbData);
455
456 if (datalen)
457 {
458 out_uint8a (s, pUrb->abData, datalen);
459 }
460
461 s_mark_end(s);
462 rdpusb_send(s);
463
464 if (pUrb->prev || pUrb->next || pUrb == proxy->urbs)
465 {
466 /* Remove the URB from list. */
467 if (pUrb->prev)
468 {
469 pUrb->prev->next = pUrb->next;
470 }
471 else
472 {
473 proxy->urbs = pUrb->next;
474 }
475
476 if (pUrb->next)
477 {
478 pUrb->next->prev = pUrb->prev;
479 }
480 }
481
482#ifdef RDPUSB_DEBUG
483 Log(("Going to free %p\n", pUrb));
484#endif
485 xfree (pUrb);
486#ifdef RDPUSB_DEBUG
487 Log(("freed %p\n", pUrb));
488#endif
489 }
490
491 proxy = proxy->next;
492 }
493
494 return;
495}
496
497static void
498rdpusb_process(STREAM s)
499{
500 int rc;
501
502 uint32 len;
503 uint8 code;
504 uint32 devid;
505
506 struct usb_proxy *proxy = NULL;
507
508#ifdef RDPUSB_DEBUG
509 Log(("RDPUSB recv:\n"));
510 hexdump(s->p, s->end - s->p);
511#endif
512
513 in_uint32_le (s, len);
514 if (len > s->end - s->p)
515 {
516 error("RDPUSB: not enough data len = %d, bytes left %d\n", len, s->end - s->p);
517 return;
518 }
519
520 in_uint8(s, code);
521
522 Log(("RDPUSB recv: len = %d, code = %d\n", len, code));
523
524 switch (code)
525 {
526 case RDPUSB_REQ_OPEN:
527 {
528 char devpath[128];
529
530 in_uint32_le(s, devid);
531
532 proxy = (struct usb_proxy *)xmalloc (sizeof (struct usb_proxy));
533
534 memset (proxy, 0, sizeof (struct usb_proxy));
535
536 proxy->Dev.pszName = "Remote device";
537 proxy->devid = devid;
538
539 sprintf (devpath, PROC_BUS_USB "/%03d/%03d", (devid>>8) & 0xFF, devid & 0xFF);
540
541 rc = op_usbproxy_back_open(proxy, devpath);
542
543 if (rc != VINF_SUCCESS)
544 {
545 rdpusb_send_access_denied (code, devid);
546 xfree (proxy);
547 proxy = NULL;
548 }
549 else
550 {
551 if (g_proxies)
552 {
553 g_proxies->prev = proxy;
554 }
555
556 proxy->next = g_proxies;
557 g_proxies = proxy;
558 }
559 } break;
560
561 case RDPUSB_REQ_CLOSE:
562 {
563 in_uint32_le(s, devid);
564 proxy = devid2proxy (devid);
565
566 if (proxy)
567 {
568 op_usbproxy_back_close(proxy);
569
570 if (proxy->prev)
571 {
572 proxy->prev->next = proxy->next;
573 }
574 else
575 {
576 g_proxies = proxy->next;
577 }
578
579 if (proxy->next)
580 {
581 proxy->next->prev = proxy->prev;
582 }
583
584 xfree (proxy);
585 proxy = NULL;
586 }
587
588 /* No reply. */
589 } break;
590
591 case RDPUSB_REQ_RESET:
592 {
593 in_uint32_le(s, devid);
594 proxy = devid2proxy (devid);
595
596 if (!proxy)
597 {
598 rdpusb_send_access_denied (code, devid);
599 break;
600 }
601
602 rc = op_usbproxy_back_reset(proxy);
603
604 if (rc != VINF_SUCCESS)
605 {
606 rdpusb_send_reply (code, vrdp_usb_status (!rc, &proxy->Dev), devid);
607 }
608 } break;
609
610 case RDPUSB_REQ_SET_CONFIG:
611 {
612 uint8 cfg;
613
614 in_uint32_le(s, devid);
615 proxy = devid2proxy (devid);
616
617 if (!proxy)
618 {
619 rdpusb_send_access_denied (code, devid);
620 break;
621 }
622
623 in_uint8(s, cfg);
624
625 rc = op_usbproxy_back_set_config(proxy, cfg);
626
627 if (!rc)
628 {
629 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
630 }
631 } break;
632
633 case RDPUSB_REQ_CLAIM_INTERFACE:
634 {
635 uint8 ifnum;
636
637 in_uint32_le(s, devid);
638 proxy = devid2proxy (devid);
639
640 if (!proxy)
641 {
642 rdpusb_send_access_denied (code, devid);
643 break;
644 }
645
646 in_uint8(s, ifnum);
647
648 rc = op_usbproxy_back_claim_interface(proxy, ifnum);
649
650 if (!rc)
651 {
652 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
653 }
654 } break;
655
656 case RDPUSB_REQ_RELEASE_INTERFACE:
657 {
658 uint8 ifnum;
659
660 in_uint32_le(s, devid);
661 proxy = devid2proxy (devid);
662
663 if (!proxy)
664 {
665 rdpusb_send_access_denied (code, devid);
666 break;
667 }
668
669 in_uint8(s, ifnum);
670
671 rc = op_usbproxy_back_release_interface(proxy, ifnum);
672
673 if (!rc)
674 {
675 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
676 }
677 } break;
678
679 case RDPUSB_REQ_INTERFACE_SETTING:
680 {
681 uint8 ifnum;
682 uint8 setting;
683
684 in_uint32_le(s, devid);
685 proxy = devid2proxy (devid);
686
687 if (!proxy)
688 {
689 rdpusb_send_access_denied (code, devid);
690 break;
691 }
692
693 in_uint8(s, ifnum);
694 in_uint8(s, setting);
695
696 rc = op_usbproxy_back_interface_setting(proxy, ifnum, setting);
697
698 if (!rc)
699 {
700 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
701 }
702 } break;
703
704 case RDPUSB_REQ_QUEUE_URB:
705 {
706 uint32 handle;
707 uint8 type;
708 uint8 ep;
709 uint8 dir;
710 uint32 urblen;
711 uint32 datalen;
712
713 PVUSBURB pUrb; // struct vusb_urb *urb;
714
715 in_uint32_le(s, devid);
716 proxy = devid2proxy (devid);
717
718 if (!proxy)
719 {
720 /* No reply. */
721 break;
722 }
723
724 in_uint32(s, handle);
725 in_uint8(s, type);
726 in_uint8(s, ep);
727 in_uint8(s, dir);
728 in_uint32(s, urblen);
729 in_uint32(s, datalen);
730
731 /* Allocate a single block for URB description and data buffer */
732 pUrb = (PVUSBURB)xmalloc (sizeof (VUSBURB) +
733 (urblen <= sizeof (pUrb->abData)? 0: urblen - sizeof (pUrb->abData))
734 );
735 memset (pUrb, 0, sizeof (VUSBURB));
736 pUrb->pDev = &proxy->Dev;
737 pUrb->handle = handle;
738 pUrb->enmType = type;
739 pUrb->enmStatus = 0;
740 pUrb->EndPt = ep;
741 pUrb->enmDir = dir;
742 pUrb->cbData = urblen;
743
744 Log(("RDPUSB: queued URB handle = %d\n", handle));
745
746 if (datalen)
747 {
748 in_uint8a (s, pUrb->abData, datalen);
749 }
750
751 rc = op_usbproxy_back_queue_urb(pUrb);
752
753 /* No reply required. */
754
755 if (rc)
756 {
757 if (proxy->urbs)
758 {
759 proxy->urbs->prev = pUrb;
760 }
761
762 pUrb->next = proxy->urbs;
763 proxy->urbs = pUrb;
764 }
765 else
766 {
767 xfree (pUrb);
768 }
769 } break;
770
771 case RDPUSB_REQ_REAP_URB:
772 {
773 rdpusb_reap_urbs ();
774 } break;
775
776 case RDPUSB_REQ_CLEAR_HALTED_EP:
777 {
778 uint8 ep;
779
780 in_uint32_le(s, devid);
781 proxy = devid2proxy (devid);
782
783 if (!proxy)
784 {
785 rdpusb_send_access_denied (code, devid);
786 break;
787 }
788
789 in_uint8(s, ep);
790
791 rc = op_usbproxy_back_clear_halted_ep(proxy, ep);
792
793 if (!rc)
794 {
795 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
796 }
797 } break;
798
799 case RDPUSB_REQ_CANCEL_URB:
800 {
801 uint32 handle;
802 PVUSBURB pUrb = NULL;
803
804 in_uint32_le(s, devid);
805 proxy = devid2proxy (devid);
806
807 if (!proxy)
808 {
809 rdpusb_send_access_denied (code, devid);
810 break;
811 }
812
813 in_uint32_le(s, handle);
814
815 pUrb = proxy->urbs;
816
817 while (pUrb && pUrb->handle != handle)
818 {
819 pUrb = pUrb->next;
820 }
821
822 if (pUrb)
823 {
824 op_usbproxy_back_cancel_urb(pUrb);
825
826 /* No reply required. */
827
828 /* Remove URB from list. */
829 if (pUrb->prev)
830 {
831 pUrb->prev->next = pUrb->next;
832 }
833 else
834 {
835 proxy->urbs = pUrb->next;
836 }
837
838 if (pUrb->next)
839 {
840 pUrb->next->prev = pUrb->prev;
841 }
842
843 pUrb->next = pUrb->prev = NULL;
844
845 Log(("Cancelled URB %p\n", pUrb));
846
847 // xfree (pUrb);
848 }
849 } break;
850
851 case RDPUSB_REQ_DEVICE_LIST:
852 {
853 void *buf = NULL;
854 int len = 0;
855
856 buf = build_device_list (&len);
857
858 s = rdpusb_init_packet(len? len: 2, code);
859 if (len)
860 {
861 out_uint8p (s, buf, len);
862 }
863 else
864 {
865 out_uint16_le(s, 0);
866 }
867 s_mark_end(s);
868 rdpusb_send(s);
869
870 if (buf)
871 {
872 free (buf);
873 }
874 } break;
875
876 case RDPUSB_REQ_NEGOTIATE:
877 {
878 s = rdpusb_init_packet(1, code);
879 out_uint8(s, VRDP_USB_CAPS_FLAG_ASYNC);
880 s_mark_end(s);
881 rdpusb_send(s);
882 } break;
883
884 default:
885 unimpl("RDPUSB code %d\n", code);
886 break;
887 }
888}
889
890void
891rdpusb_add_fds(int *n, fd_set * rfds, fd_set * wfds)
892{
893 struct usb_proxy *proxy = g_proxies;
894
895// Log(("RDPUSB: rdpusb_add_fds: begin *n = %d\n", *n));
896
897 while (proxy)
898 {
899 int fd = dev2fd(proxy);
900
901 if (fd != -1)
902 {
903// Log(("RDPUSB: rdpusb_add_fds: adding %d\n", proxy->priv.File));
904
905 FD_SET(fd, rfds);
906 FD_SET(fd, wfds);
907 *n = MAX(*n, fd);
908 }
909
910 proxy = proxy->next;
911 }
912
913// Log(("RDPUSB: rdpusb_add_fds: end *n = %d\n", *n));
914
915 return;
916}
917
918void
919rdpusb_check_fds(fd_set * rfds, fd_set * wfds)
920{
921 (void)rfds;
922 (void)wfds;
923
924// Log(("RDPUSB: rdpusb_check_fds: begin\n"));
925
926 rdpusb_reap_urbs ();
927
928// Log(("RDPUSB: rdpusb_check_fds: end\n"));
929
930 return;
931}
932
933BOOL
934rdpusb_init(void)
935{
936 rdpusb_channel =
937 channel_register("vrdpusb", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
938 rdpusb_process);
939 return (rdpusb_channel != NULL);
940}
941
942void
943rdpusb_close (void)
944{
945 struct usb_proxy *proxy = g_proxies;
946
947 while (proxy)
948 {
949 struct usb_proxy *next = proxy->next;
950
951 Log(("RDPUSB: closing proxy %p\n", proxy));
952
953 op_usbproxy_back_close(proxy);
954 xfree (proxy);
955
956 proxy = next;
957 }
958
959 return;
960}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette