VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.3/vrdp/rdpusb.c@ 55123

Last change on this file since 55123 was 54780, checked in by vboxsync, 10 years ago

RDP/client: fixed several regressions after r93776 due to changed return types of the proxy functions

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.8 KB
Line 
1/** @file
2 *
3 * Remote Desktop Protocol client:
4 * USB Channel Process Functions
5 *
6 */
7
8/*
9 * Copyright (C) 2006-2011 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/* DEBUG is defined in ../rdesktop.h */
21#ifdef DEBUG
22# define VBOX_DEBUG DEBUG
23#endif
24#include "../rdesktop.h"
25#undef DEBUG
26#ifdef VBOX_DEBUG
27# define DEBUG VBOX_DEBUG
28#endif
29
30#include "vrdpusb.h"
31#include "USBProxyDevice.h"
32#include "USBGetDevices.h"
33
34#include <iprt/cdefs.h>
35#include <iprt/types.h>
36#include <iprt/err.h>
37#include <iprt/log.h>
38
39#include <unistd.h>
40#include <ctype.h>
41#include <fcntl.h>
42
43
44#define RDPUSB_REQ_OPEN (0)
45#define RDPUSB_REQ_CLOSE (1)
46#define RDPUSB_REQ_RESET (2)
47#define RDPUSB_REQ_SET_CONFIG (3)
48#define RDPUSB_REQ_CLAIM_INTERFACE (4)
49#define RDPUSB_REQ_RELEASE_INTERFACE (5)
50#define RDPUSB_REQ_INTERFACE_SETTING (6)
51#define RDPUSB_REQ_QUEUE_URB (7)
52#define RDPUSB_REQ_REAP_URB (8)
53#define RDPUSB_REQ_CLEAR_HALTED_EP (9)
54#define RDPUSB_REQ_CANCEL_URB (10)
55#define RDPUSB_REQ_DEVICE_LIST (11)
56#define RDPUSB_REQ_NEGOTIATE (12)
57
58static VCHANNEL *rdpusb_channel;
59
60/** Well-known locations for the Linux Usbfs virtual file system */
61static const struct
62{
63 /** Expected mount location for Usbfs */
64 const char *pcszRoot;
65 /** Expected location of the "devices" file */
66 const char *pcszDevices;
67} g_usbfsPaths[] =
68{
69 { "/proc/bus/usb", "/proc/bus/usb/devices" },
70 { "/dev/bus/usb", "/dev/bus/usb/devices" }
71};
72
73/** Location at which the USB device tree was found. NULL means not
74 * found. */
75static const char *g_pcszDevicesRoot = NULL;
76static bool g_fUseSysfs = false;
77
78static PUSBDEVICE g_pUsbDevices = NULL;
79
80/* A device list entry */
81#pragma pack (1)
82typedef struct _DevListEntry
83{
84 uint16_t oNext; /* Offset of the next structure. 0 if last. */
85 uint32_t id; /* Identifier of the device assigned by the client. */
86 uint16_t bcdUSB; /* USB verion number. */
87 uint8_t bDeviceClass; /* Device class. */
88 uint8_t bDeviceSubClass; /* Device subclass. */
89 uint8_t bDeviceProtocol; /* Device protocol. */
90 uint16_t idVendor; /* Vendor id. */
91 uint16_t idProduct; /* Product id. */
92 uint16_t bcdRev; /* Revision. */
93 uint16_t oManufacturer; /* Offset of manufacturer string. */
94 uint16_t oProduct; /* Offset of product string. */
95 uint16_t oSerialNumber; /* Offset of serial string. */
96 uint16_t idPort; /* Physical USB port the device is connected to. */
97} DevListEntry;
98#pragma pack ()
99
100/**
101 * @returns VBox status code.
102 */
103static inline int op_usbproxy_back_open(PUSBPROXYDEV p, const char *pszAddress)
104{
105 return g_USBProxyDeviceHost.pfnOpen (p, pszAddress, NULL);
106}
107
108static inline void op_usbproxy_back_close(PUSBPROXYDEV pDev)
109{
110 return g_USBProxyDeviceHost.pfnClose (pDev);
111}
112
113/**
114 * @returns VBox status code.
115 */
116static inline int op_usbproxy_back_reset(PUSBPROXYDEV pDev)
117{
118 return g_USBProxyDeviceHost.pfnReset (pDev, false);
119}
120
121/**
122 * @returns VBox status code.
123 */
124static inline int op_usbproxy_back_set_config(PUSBPROXYDEV pDev, int cfg)
125{
126 return g_USBProxyDeviceHost.pfnSetConfig (pDev, cfg);
127}
128
129/**
130 * @returns VBox status code.
131 */
132static inline int op_usbproxy_back_claim_interface(PUSBPROXYDEV pDev, int ifnum)
133{
134 return g_USBProxyDeviceHost.pfnClaimInterface (pDev, ifnum);
135}
136
137/**
138 * @returns VBox status code.
139 */
140static inline int op_usbproxy_back_release_interface(PUSBPROXYDEV pDev, int ifnum)
141{
142 return g_USBProxyDeviceHost.pfnReleaseInterface (pDev, ifnum);
143}
144
145/**
146 * @returns VBox status code.
147 */
148static inline int op_usbproxy_back_interface_setting(PUSBPROXYDEV pDev, int ifnum, int setting)
149{
150 return g_USBProxyDeviceHost.pfnSetInterface (pDev, ifnum, setting);
151}
152
153/**
154 * @returns VBox status code.
155 */
156static inline int op_usbproxy_back_queue_urb(PUSBPROXYDEV pDev, PVUSBURB pUrb)
157{
158 return g_USBProxyDeviceHost.pfnUrbQueue(pDev, pUrb);
159}
160
161static inline PVUSBURB op_usbproxy_back_reap_urb(PUSBPROXYDEV pDev, unsigned cMillies)
162{
163 return g_USBProxyDeviceHost.pfnUrbReap (pDev, cMillies);
164}
165
166/**
167 * @returns VBox status code.
168 */
169static inline int op_usbproxy_back_clear_halted_ep(PUSBPROXYDEV pDev, unsigned EndPoint)
170{
171 return g_USBProxyDeviceHost.pfnClearHaltedEndpoint (pDev, EndPoint);
172}
173
174/**
175 * @returns VBox status code.
176 */
177static inline int op_usbproxy_back_cancel_urb(PUSBPROXYDEV pDev, PVUSBURB pUrb)
178{
179 return g_USBProxyDeviceHost.pfnUrbCancel (pDev, pUrb);
180}
181
182
183/** Count the USB devices in a linked list of PUSBDEVICE structures. */
184unsigned countUSBDevices(PUSBDEVICE pDevices)
185{
186 unsigned i = 0;
187 for (; pDevices; pDevices = pDevices->pNext)
188 ++i;
189 return i;
190}
191
192
193enum {
194 /** The space we set aside for the USB strings. Should always be enough,
195 * as a USB device contains up to 256 characters of UTF-16 string data. */
196 MAX_STRINGS_LEN = 1024,
197 /** The space we reserve for each wire format device entry */
198 DEV_ENTRY_SIZE = sizeof(DevListEntry) + MAX_STRINGS_LEN
199};
200
201
202/**
203 * Add a string to the end of a wire format device entry.
204 * @param pBuf the start of the buffer containing the entry
205 * @param iBuf the index into the buffer to add the string at
206 * @param pcsz the string to add - optional
207 * @param piString where to write back @a iBuf or zero if there is no string
208 * @param piNext where to write back the index where the next string may
209 * start
210 */
211static void addStringToEntry(char *pBuf, uint16_t iBuf, const char *pcsz,
212 uint16_t *piString, uint16_t *piNext)
213{
214 size_t cch;
215
216 *piString = 0;
217 *piNext = iBuf;
218 if (!pcsz)
219 return;
220 cch = strlen(pcsz) + 1;
221 if (cch > DEV_ENTRY_SIZE - iBuf)
222 return;
223 strcpy(pBuf + iBuf, pcsz);
224 *piString = iBuf;
225 *piNext = iBuf + cch;
226}
227
228
229/** Fill in a device list entry in wire format from a PUSBDEVICE and return an
230 * index to where the next string should start */
231static void fillWireListEntry(char *pBuf, PUSBDEVICE pDevice,
232 uint16_t *piNext)
233{
234 DevListEntry *pEntry;
235 uint16_t iNextString = sizeof(DevListEntry);
236
237 pEntry = (DevListEntry *)pBuf;
238 pEntry->id = (pDevice->bPort << 8) + pDevice->bBus;
239 pEntry->bcdUSB = pDevice->bcdUSB;
240 pEntry->bDeviceClass = pDevice->bDeviceClass;
241 pEntry->bDeviceSubClass = pDevice->bDeviceSubClass;
242 pEntry->idVendor = pDevice->idVendor;
243 pEntry->idProduct = pDevice->idProduct;
244 pEntry->bcdRev = pDevice->bcdDevice;
245 pEntry->idPort = pDevice->bPort;
246 addStringToEntry(pBuf, iNextString, pDevice->pszManufacturer,
247 &pEntry->oManufacturer, &iNextString);
248 addStringToEntry(pBuf, iNextString, pDevice->pszProduct,
249 &pEntry->oProduct, &iNextString);
250 addStringToEntry(pBuf, iNextString, pDevice->pszSerialNumber,
251 &pEntry->oSerialNumber, &pEntry->oNext);
252 *piNext = pEntry->oNext;
253}
254
255
256/** Allocate (and return) a buffer for a device list in VRDP wire format,
257 * and populate from a PUSBDEVICE linked list. @a pLen takes the length of
258 * the new list.
259 * See @a Console::processRemoteUSBDevices for the receiving end. */
260static void *buildWireListFromDevices(PUSBDEVICE pDevices, int *pLen)
261{
262 char *pBuf;
263 unsigned cDevs, cbBuf, iCurrent;
264 uint16_t iNext;
265 PUSBDEVICE pCurrent;
266
267 cDevs = countUSBDevices(pDevices);
268 cbBuf = cDevs * DEV_ENTRY_SIZE + 2;
269 pBuf = (char *)xmalloc(cbBuf);
270 memset(pBuf, 0, cbBuf);
271 for (pCurrent = pDevices, iCurrent = 0; pCurrent;
272 pCurrent = pCurrent->pNext, iCurrent += iNext, --cDevs)
273 {
274 unsigned i, cZeros;
275
276 AssertReturnStmt(iCurrent + DEV_ENTRY_SIZE + 2 <= cbBuf,
277 free(pBuf), NULL);
278 fillWireListEntry(pBuf + iCurrent, pCurrent, &iNext);
279 DevListEntry *pEntry = (DevListEntry *)(pBuf + iCurrent);
280 /* Sanity tests */
281 for (i = iCurrent + sizeof(DevListEntry), cZeros = 0;
282 i < iCurrent + iNext; ++i)
283 if (pBuf[i] == 0)
284 ++cZeros;
285 AssertReturnStmt(cZeros == RT_BOOL(pEntry->oManufacturer)
286 + RT_BOOL(pEntry->oProduct)
287 + RT_BOOL(pEntry->oSerialNumber),
288 free(pBuf), NULL);
289 Assert(pEntry->oManufacturer == 0 || pBuf[iCurrent + pEntry->oManufacturer] != '\0');
290 Assert(pEntry->oProduct == 0 || pBuf[iCurrent + pEntry->oProduct] != '\0');
291 Assert(pEntry->oSerialNumber == 0 || pBuf[iCurrent + pEntry->oSerialNumber] != '\0');
292 AssertReturnStmt(cZeros == 0 || pBuf[iCurrent + iNext - 1] == '\0',
293 free(pBuf), NULL);
294 }
295 *pLen = iCurrent + iNext + 2;
296 Assert(cDevs == 0);
297 Assert(*pLen <= cbBuf);
298 return pBuf;
299}
300
301
302/** Build a list of the usable USB devices currently connected to the client
303 * system using the VRDP wire protocol. The structure returned must be freed
304 * using free(3) when it is no longer needed; returns NULL and sets *pLen to
305 * zero on failure. */
306static void *build_device_list (int *pLen)
307{
308 void *pvDeviceList;
309
310 Log(("RDPUSB build_device_list"));
311 *pLen = 0;
312 if (g_pUsbDevices)
313 deviceListFree(&g_pUsbDevices);
314 g_pUsbDevices = USBProxyLinuxGetDevices(g_pcszDevicesRoot, g_fUseSysfs);
315 if (!g_pUsbDevices)
316 return NULL;
317 pvDeviceList = buildWireListFromDevices(g_pUsbDevices, pLen);
318 return pvDeviceList;
319}
320
321
322static STREAM
323rdpusb_init_packet(uint32 len, uint8 code)
324{
325 STREAM s;
326
327 s = channel_init(rdpusb_channel, len + 5);
328 out_uint32_le (s, len + sizeof (code)); /* The length of data after the 'len' field. */
329 out_uint8(s, code);
330 return s;
331}
332
333static void
334rdpusb_send(STREAM s)
335{
336#ifdef RDPUSB_DEBUG
337 Log(("RDPUSB send:\n"));
338 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
339#endif
340
341 channel_send(s, rdpusb_channel);
342}
343
344static void
345rdpusb_send_reply (uint8_t code, uint8_t status, uint32_t devid)
346{
347 STREAM s = rdpusb_init_packet(5, code);
348 out_uint8(s, status);
349 out_uint32_le(s, devid);
350 s_mark_end(s);
351 rdpusb_send(s);
352}
353
354static void
355rdpusb_send_access_denied (uint8_t code, uint32_t devid)
356{
357 rdpusb_send_reply (code, VRDP_USB_STATUS_ACCESS_DENIED, devid);
358}
359
360static inline int
361vrdp_usb_status (int rc, VUSBDEV *pdev)
362{
363 if (!rc || usbProxyFromVusbDev(pdev)->fDetached)
364 {
365 return VRDP_USB_STATUS_DEVICE_REMOVED;
366 }
367
368 return VRDP_USB_STATUS_SUCCESS;
369}
370
371static PUSBPROXYDEV g_proxies = NULL;
372
373static PUSBPROXYDEV
374devid2proxy (uint32_t devid)
375{
376 PUSBPROXYDEV proxy = g_proxies;
377
378 while (proxy && proxy->devid != devid)
379 {
380 proxy = proxy->pNext;
381 }
382
383 return proxy;
384}
385
386static void
387rdpusb_reap_urbs (void)
388{
389 STREAM s;
390
391 PVUSBURB pUrb = NULL;
392
393 PUSBPROXYDEV proxy = g_proxies;
394
395 while (proxy)
396 {
397 pUrb = op_usbproxy_back_reap_urb(proxy, 0);
398
399 if (pUrb)
400 {
401 int datalen = 0;
402
403 Log(("RDPUSB: rdpusb_reap_urbs: cbData = %d, enmStatus = %d\n", pUrb->cbData, pUrb->enmStatus));
404
405 if (pUrb->enmDir == VUSB_DIRECTION_IN)
406 {
407 datalen = pUrb->cbData;
408 }
409
410 s = rdpusb_init_packet(14 + datalen, RDPUSB_REQ_REAP_URB);
411 out_uint32_le(s, proxy->devid);
412 out_uint8(s, VRDP_USB_REAP_FLAG_LAST);
413 out_uint8(s, pUrb->enmStatus);
414 out_uint32_le(s, pUrb->handle);
415 out_uint32_le(s, pUrb->cbData);
416
417 if (datalen)
418 {
419 out_uint8a (s, pUrb->abData, datalen);
420 }
421
422 s_mark_end(s);
423 rdpusb_send(s);
424
425 if (pUrb->pPrev || pUrb->pNext || pUrb == proxy->pUrbs)
426 {
427 /* Remove the URB from list. */
428 if (pUrb->pPrev)
429 {
430 pUrb->pPrev->pNext = pUrb->pNext;
431 }
432 else
433 {
434 proxy->pUrbs = pUrb->pNext;
435 }
436
437 if (pUrb->pNext)
438 {
439 pUrb->pNext->pPrev = pUrb->pPrev;
440 }
441 }
442
443#ifdef RDPUSB_DEBUG
444 Log(("Going to free %p\n", pUrb));
445#endif
446 xfree (pUrb);
447#ifdef RDPUSB_DEBUG
448 Log(("freed %p\n", pUrb));
449#endif
450 }
451
452 proxy = proxy->pNext;
453 }
454
455 return;
456}
457
458static void
459rdpusb_process(STREAM s)
460{
461 int rc;
462
463 uint32 len;
464 uint8 code;
465 uint32 devid;
466
467 PUSBPROXYDEV proxy = NULL;
468
469#ifdef RDPUSB_DEBUG
470 Log(("RDPUSB recv:\n"));
471 hexdump(s->p, s->end - s->p);
472#endif
473
474 in_uint32_le (s, len);
475 if (len > s->end - s->p)
476 {
477 error("RDPUSB: not enough data len = %d, bytes left %d\n", len, s->end - s->p);
478 return;
479 }
480
481 in_uint8(s, code);
482
483 Log(("RDPUSB recv: len = %d, code = %d\n", len, code));
484
485 switch (code)
486 {
487 case RDPUSB_REQ_OPEN:
488 {
489 PUSBDEVICE pDevice;
490
491 in_uint32_le(s, devid);
492
493 proxy = (PUSBPROXYDEV )xmalloc (sizeof (USBPROXYDEV));
494 if (!proxy)
495 {
496 error("RDPUSB: Out of memory allocating proxy backend data\n");
497 return;
498 }
499
500 memset (proxy, 0, sizeof (USBPROXYDEV));
501
502 proxy->pvInstanceDataR3 = xmalloc(g_USBProxyDeviceHost.cbBackend);
503 if (!proxy->pvInstanceDataR3)
504 {
505 error("RDPUSB: Out of memory allocating proxy backend data\n");
506 return;
507 }
508
509 proxy->Dev.pszName = "Remote device";
510 proxy->devid = devid;
511
512 for (pDevice = g_pUsbDevices; pDevice; pDevice = pDevice->pNext)
513 if ((pDevice->bPort << 8) + pDevice->bBus == devid)
514 break;
515
516 rc = pDevice ? op_usbproxy_back_open(proxy, pDevice->pszAddress)
517 : VERR_NOT_FOUND;
518
519 if (rc != VINF_SUCCESS)
520 {
521 rdpusb_send_access_denied (code, devid);
522 xfree (proxy);
523 proxy = NULL;
524 }
525 else
526 {
527 if (g_proxies)
528 {
529 g_proxies->pPrev = proxy;
530 }
531
532 proxy->pNext = g_proxies;
533 g_proxies = proxy;
534 }
535 } break;
536
537 case RDPUSB_REQ_CLOSE:
538 {
539 in_uint32_le(s, devid);
540 proxy = devid2proxy (devid);
541
542 if (proxy)
543 {
544 op_usbproxy_back_close(proxy);
545
546 if (proxy->pPrev)
547 {
548 proxy->pPrev->pNext = proxy->pNext;
549 }
550 else
551 {
552 g_proxies = proxy->pNext;
553 }
554
555 if (proxy->pNext)
556 {
557 proxy->pNext->pPrev = proxy->pPrev;
558 }
559
560 xfree (proxy->pvInstanceDataR3);
561 xfree (proxy);
562 proxy = NULL;
563 }
564
565 /* No reply. */
566 } break;
567
568 case RDPUSB_REQ_RESET:
569 {
570 in_uint32_le(s, devid);
571 proxy = devid2proxy (devid);
572
573 if (!proxy)
574 {
575 rdpusb_send_access_denied (code, devid);
576 break;
577 }
578
579 rc = op_usbproxy_back_reset(proxy);
580 if (rc != VINF_SUCCESS)
581 {
582 rdpusb_send_reply (code, vrdp_usb_status (!rc, &proxy->Dev), devid);
583 }
584 } break;
585
586 case RDPUSB_REQ_SET_CONFIG:
587 {
588 uint8 cfg;
589
590 in_uint32_le(s, devid);
591 proxy = devid2proxy (devid);
592
593 if (!proxy)
594 {
595 rdpusb_send_access_denied (code, devid);
596 break;
597 }
598
599 in_uint8(s, cfg);
600
601 rc = op_usbproxy_back_set_config(proxy, cfg);
602 if (RT_FAILURE(rc))
603 {
604 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
605 }
606 } break;
607
608 case RDPUSB_REQ_CLAIM_INTERFACE:
609 {
610 uint8 ifnum;
611
612 in_uint32_le(s, devid);
613 proxy = devid2proxy (devid);
614
615 if (!proxy)
616 {
617 rdpusb_send_access_denied (code, devid);
618 break;
619 }
620
621 in_uint8(s, ifnum);
622 in_uint8(s, ifnum);
623
624 rc = op_usbproxy_back_claim_interface(proxy, ifnum);
625 if (RT_FAILURE(rc))
626 {
627 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
628 }
629 } break;
630
631 case RDPUSB_REQ_RELEASE_INTERFACE:
632 {
633 uint8 ifnum;
634
635 in_uint32_le(s, devid);
636 proxy = devid2proxy (devid);
637
638 if (!proxy)
639 {
640 rdpusb_send_access_denied (code, devid);
641 break;
642 }
643
644 in_uint8(s, ifnum);
645
646 rc = op_usbproxy_back_release_interface(proxy, ifnum);
647 if (RT_FAILURE(rc))
648 {
649 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
650 }
651 } break;
652
653 case RDPUSB_REQ_INTERFACE_SETTING:
654 {
655 uint8 ifnum;
656 uint8 setting;
657
658 in_uint32_le(s, devid);
659 proxy = devid2proxy (devid);
660
661 if (!proxy)
662 {
663 rdpusb_send_access_denied (code, devid);
664 break;
665 }
666
667 in_uint8(s, ifnum);
668 in_uint8(s, setting);
669
670 rc = op_usbproxy_back_interface_setting(proxy, ifnum, setting);
671 if (RT_FAILURE(rc))
672 {
673 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
674 }
675 } break;
676
677 case RDPUSB_REQ_QUEUE_URB:
678 {
679 uint32 handle;
680 uint8 type;
681 uint8 ep;
682 uint8 dir;
683 uint32 urblen;
684 uint32 datalen;
685
686 PVUSBURB pUrb; // struct vusb_urb *urb;
687
688 in_uint32_le(s, devid);
689 proxy = devid2proxy (devid);
690
691 if (!proxy)
692 {
693 /* No reply. */
694 break;
695 }
696
697 in_uint32(s, handle);
698 in_uint8(s, type);
699 in_uint8(s, ep);
700 in_uint8(s, dir);
701 in_uint32(s, urblen);
702 in_uint32(s, datalen);
703
704 /* Allocate a single block for URB description and data buffer */
705 pUrb = (PVUSBURB)xmalloc (sizeof (VUSBURB) +
706 (urblen <= sizeof (pUrb->abData)? 0: urblen - sizeof (pUrb->abData))
707 );
708 memset (pUrb, 0, sizeof (VUSBURB));
709 pUrb->pDev = &proxy->Dev;
710 pUrb->handle = handle;
711 pUrb->enmType = type;
712 pUrb->enmStatus = 0;
713 pUrb->EndPt = ep;
714 pUrb->enmDir = dir;
715 pUrb->cbData = urblen;
716
717 Log(("RDPUSB: queued URB handle = %d\n", handle));
718
719 if (datalen)
720 {
721 in_uint8a (s, pUrb->abData, datalen);
722 }
723
724 rc = op_usbproxy_back_queue_urb(proxy, pUrb);
725
726 /* No reply required. */
727
728 if (RT_SUCCESS(rc))
729 {
730 if (proxy->pUrbs)
731 {
732 proxy->pUrbs->pPrev = pUrb;
733 }
734
735 pUrb->pNext = proxy->pUrbs;
736 proxy->pUrbs = pUrb;
737 }
738 else
739 {
740 xfree (pUrb);
741 }
742 } break;
743
744 case RDPUSB_REQ_REAP_URB:
745 {
746 rdpusb_reap_urbs ();
747 } break;
748
749 case RDPUSB_REQ_CLEAR_HALTED_EP:
750 {
751 uint8 ep;
752
753 in_uint32_le(s, devid);
754 proxy = devid2proxy (devid);
755
756 if (!proxy)
757 {
758 rdpusb_send_access_denied (code, devid);
759 break;
760 }
761
762 in_uint8(s, ep);
763
764 rc = op_usbproxy_back_clear_halted_ep(proxy, ep);
765 if (RT_FAILURE(rc))
766 {
767 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
768 }
769 } break;
770
771 case RDPUSB_REQ_CANCEL_URB:
772 {
773 uint32 handle;
774 PVUSBURB pUrb = NULL;
775
776 in_uint32_le(s, devid);
777 proxy = devid2proxy (devid);
778
779 if (!proxy)
780 {
781 rdpusb_send_access_denied (code, devid);
782 break;
783 }
784
785 in_uint32_le(s, handle);
786
787 pUrb = proxy->pUrbs;
788
789 while (pUrb && pUrb->handle != handle)
790 {
791 pUrb = pUrb->pNext;
792 }
793
794 if (pUrb)
795 {
796 op_usbproxy_back_cancel_urb(proxy, pUrb);
797
798 /* No reply required. */
799
800 /* Remove URB from list. */
801 if (pUrb->pPrev)
802 {
803 pUrb->pPrev->pNext = pUrb->pNext;
804 }
805 else
806 {
807 proxy->pUrbs = pUrb->pNext;
808 }
809
810 if (pUrb->pNext)
811 {
812 pUrb->pNext->pPrev = pUrb->pPrev;
813 }
814
815 pUrb->pNext = pUrb->pPrev = NULL;
816
817 Log(("Cancelled URB %p\n", pUrb));
818
819 // xfree (pUrb);
820 }
821 } break;
822
823 case RDPUSB_REQ_DEVICE_LIST:
824 {
825 void *buf = NULL;
826 int len = 0;
827
828 buf = build_device_list (&len);
829
830 s = rdpusb_init_packet(len? len: 2, code);
831 if (len)
832 {
833 out_uint8p (s, buf, len);
834 }
835 else
836 {
837 out_uint16_le(s, 0);
838 }
839 s_mark_end(s);
840 rdpusb_send(s);
841
842 if (buf)
843 {
844 free (buf);
845 }
846 } break;
847
848 case RDPUSB_REQ_NEGOTIATE:
849 {
850 s = rdpusb_init_packet(1, code);
851 out_uint8(s, VRDP_USB_CAPS_FLAG_ASYNC);
852 s_mark_end(s);
853 rdpusb_send(s);
854 } break;
855
856 default:
857 unimpl("RDPUSB code %d\n", code);
858 break;
859 }
860}
861
862void
863rdpusb_add_fds(int *n, fd_set * rfds, fd_set * wfds)
864{
865 PUSBPROXYDEV proxy = g_proxies;
866
867// Log(("RDPUSB: rdpusb_add_fds: begin *n = %d\n", *n));
868
869 while (proxy)
870 {
871 int fd = USBProxyDeviceLinuxGetFD(proxy);
872
873 if (fd != -1)
874 {
875// Log(("RDPUSB: rdpusb_add_fds: adding %d\n", proxy->priv.File));
876
877 FD_SET(fd, rfds);
878 FD_SET(fd, wfds);
879 *n = MAX(*n, fd);
880 }
881
882 proxy = proxy->pNext;
883 }
884
885// Log(("RDPUSB: rdpusb_add_fds: end *n = %d\n", *n));
886
887 return;
888}
889
890void
891rdpusb_check_fds(fd_set * rfds, fd_set * wfds)
892{
893 PUSBPROXYDEV proxy = g_proxies;
894 unsigned found = 0;
895
896 while (proxy)
897 {
898 int fd = USBProxyDeviceLinuxGetFD(proxy);
899
900 if (fd != -1)
901 {
902 if (FD_ISSET(fd, rfds))
903 found = 1;
904 if (FD_ISSET(fd, wfds))
905 found = 1;
906 }
907
908 proxy = proxy->pNext;
909 }
910
911// Log(("RDPUSB: rdpusb_check_fds: begin\n"));
912
913 if (found)
914 rdpusb_reap_urbs ();
915
916// Log(("RDPUSB: rdpusb_check_fds: end\n"));
917
918 return;
919}
920
921
922RD_BOOL
923rdpusb_init(void)
924{
925 bool fUseUsbfs;
926 if (RT_SUCCESS(USBProxyLinuxChooseMethod(&fUseUsbfs, &g_pcszDevicesRoot)))
927 {
928 g_fUseSysfs = !fUseUsbfs;
929 rdpusb_channel =
930 channel_register("vrdpusb", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
931 rdpusb_process);
932 return (rdpusb_channel != NULL);
933 }
934 return false;
935}
936
937void
938rdpusb_close (void)
939{
940 PUSBPROXYDEV proxy = g_proxies;
941
942 while (proxy)
943 {
944 PUSBPROXYDEV pNext = proxy->pNext;
945
946 Log(("RDPUSB: closing proxy %p\n", proxy));
947
948 op_usbproxy_back_close(proxy);
949 xfree (proxy);
950
951 proxy = pNext;
952 }
953
954 return;
955}
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