VirtualBox

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

Last change on this file since 31658 was 31247, checked in by vboxsync, 15 years ago

RDP/client: updates to the RDP client code

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

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