VirtualBox

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

Last change on this file since 14833 was 9902, checked in by vboxsync, 16 years ago

Added rdesktop 1.6.0.

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

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