VirtualBox

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

Last change on this file since 69046 was 58158, checked in by vboxsync, 9 years ago

USBPROXYDEV: nits.

  • 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->idVrdp != 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->idVrdp);
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 xfree (proxy);
506 error("RDPUSB: Out of memory allocating proxy backend data\n");
507 return;
508 }
509
510 proxy->Dev.pszName = "Remote device";
511 proxy->idVrdp = devid;
512
513 for (pDevice = g_pUsbDevices; pDevice; pDevice = pDevice->pNext)
514 if ((pDevice->bPort << 8) + pDevice->bBus == devid)
515 break;
516
517 rc = pDevice ? op_usbproxy_back_open(proxy, pDevice->pszAddress)
518 : VERR_NOT_FOUND;
519
520 if (rc != VINF_SUCCESS)
521 {
522 rdpusb_send_access_denied (code, devid);
523 xfree (proxy);
524 proxy = NULL;
525 }
526 else
527 {
528 if (g_proxies)
529 {
530 g_proxies->pPrev = proxy;
531 }
532
533 proxy->pNext = g_proxies;
534 g_proxies = proxy;
535 }
536 } break;
537
538 case RDPUSB_REQ_CLOSE:
539 {
540 in_uint32_le(s, devid);
541 proxy = devid2proxy (devid);
542
543 if (proxy)
544 {
545 op_usbproxy_back_close(proxy);
546
547 if (proxy->pPrev)
548 {
549 proxy->pPrev->pNext = proxy->pNext;
550 }
551 else
552 {
553 g_proxies = proxy->pNext;
554 }
555
556 if (proxy->pNext)
557 {
558 proxy->pNext->pPrev = proxy->pPrev;
559 }
560
561 xfree (proxy->pvInstanceDataR3);
562 xfree (proxy);
563 proxy = NULL;
564 }
565
566 /* No reply. */
567 } break;
568
569 case RDPUSB_REQ_RESET:
570 {
571 in_uint32_le(s, devid);
572 proxy = devid2proxy (devid);
573
574 if (!proxy)
575 {
576 rdpusb_send_access_denied (code, devid);
577 break;
578 }
579
580 rc = op_usbproxy_back_reset(proxy);
581 if (rc != VINF_SUCCESS)
582 {
583 rdpusb_send_reply (code, vrdp_usb_status (!rc, &proxy->Dev), devid);
584 }
585 } break;
586
587 case RDPUSB_REQ_SET_CONFIG:
588 {
589 uint8 cfg;
590
591 in_uint32_le(s, devid);
592 proxy = devid2proxy (devid);
593
594 if (!proxy)
595 {
596 rdpusb_send_access_denied (code, devid);
597 break;
598 }
599
600 in_uint8(s, cfg);
601
602 rc = op_usbproxy_back_set_config(proxy, cfg);
603 if (RT_FAILURE(rc))
604 {
605 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
606 }
607 } break;
608
609 case RDPUSB_REQ_CLAIM_INTERFACE:
610 {
611 uint8 ifnum;
612
613 in_uint32_le(s, devid);
614 proxy = devid2proxy (devid);
615
616 if (!proxy)
617 {
618 rdpusb_send_access_denied (code, devid);
619 break;
620 }
621
622 in_uint8(s, ifnum);
623 in_uint8(s, ifnum);
624
625 rc = op_usbproxy_back_claim_interface(proxy, ifnum);
626 if (RT_FAILURE(rc))
627 {
628 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
629 }
630 } break;
631
632 case RDPUSB_REQ_RELEASE_INTERFACE:
633 {
634 uint8 ifnum;
635
636 in_uint32_le(s, devid);
637 proxy = devid2proxy (devid);
638
639 if (!proxy)
640 {
641 rdpusb_send_access_denied (code, devid);
642 break;
643 }
644
645 in_uint8(s, ifnum);
646
647 rc = op_usbproxy_back_release_interface(proxy, ifnum);
648 if (RT_FAILURE(rc))
649 {
650 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
651 }
652 } break;
653
654 case RDPUSB_REQ_INTERFACE_SETTING:
655 {
656 uint8 ifnum;
657 uint8 setting;
658
659 in_uint32_le(s, devid);
660 proxy = devid2proxy (devid);
661
662 if (!proxy)
663 {
664 rdpusb_send_access_denied (code, devid);
665 break;
666 }
667
668 in_uint8(s, ifnum);
669 in_uint8(s, setting);
670
671 rc = op_usbproxy_back_interface_setting(proxy, ifnum, setting);
672 if (RT_FAILURE(rc))
673 {
674 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
675 }
676 } break;
677
678 case RDPUSB_REQ_QUEUE_URB:
679 {
680 uint32 handle;
681 uint8 type;
682 uint8 ep;
683 uint8 dir;
684 uint32 urblen;
685 uint32 datalen;
686
687 PVUSBURB pUrb; // struct vusb_urb *urb;
688
689 in_uint32_le(s, devid);
690 proxy = devid2proxy (devid);
691
692 if (!proxy)
693 {
694 /* No reply. */
695 break;
696 }
697
698 in_uint32(s, handle);
699 in_uint8(s, type);
700 in_uint8(s, ep);
701 in_uint8(s, dir);
702 in_uint32(s, urblen);
703 in_uint32(s, datalen);
704
705 /* Allocate a single block for URB description and data buffer */
706 pUrb = (PVUSBURB)xmalloc (sizeof (VUSBURB) +
707 (urblen <= sizeof (pUrb->abData)? 0: urblen - sizeof (pUrb->abData))
708 );
709 memset (pUrb, 0, sizeof (VUSBURB));
710 pUrb->pDev = &proxy->Dev;
711 pUrb->handle = handle;
712 pUrb->enmType = type;
713 pUrb->enmStatus = 0;
714 pUrb->EndPt = ep;
715 pUrb->enmDir = dir;
716 pUrb->cbData = urblen;
717
718 Log(("RDPUSB: queued URB handle = %d\n", handle));
719
720 if (datalen)
721 {
722 in_uint8a (s, pUrb->abData, datalen);
723 }
724
725 rc = op_usbproxy_back_queue_urb(proxy, pUrb);
726
727 /* No reply required. */
728
729 if (RT_SUCCESS(rc))
730 {
731 if (proxy->pUrbs)
732 {
733 proxy->pUrbs->pPrev = pUrb;
734 }
735
736 pUrb->pNext = proxy->pUrbs;
737 proxy->pUrbs = pUrb;
738 }
739 else
740 {
741 xfree (pUrb);
742 }
743 } break;
744
745 case RDPUSB_REQ_REAP_URB:
746 {
747 rdpusb_reap_urbs ();
748 } break;
749
750 case RDPUSB_REQ_CLEAR_HALTED_EP:
751 {
752 uint8 ep;
753
754 in_uint32_le(s, devid);
755 proxy = devid2proxy (devid);
756
757 if (!proxy)
758 {
759 rdpusb_send_access_denied (code, devid);
760 break;
761 }
762
763 in_uint8(s, ep);
764
765 rc = op_usbproxy_back_clear_halted_ep(proxy, ep);
766 if (RT_FAILURE(rc))
767 {
768 rdpusb_send_reply (code, vrdp_usb_status (rc, &proxy->Dev), devid);
769 }
770 } break;
771
772 case RDPUSB_REQ_CANCEL_URB:
773 {
774 uint32 handle;
775 PVUSBURB pUrb = NULL;
776
777 in_uint32_le(s, devid);
778 proxy = devid2proxy (devid);
779
780 if (!proxy)
781 {
782 rdpusb_send_access_denied (code, devid);
783 break;
784 }
785
786 in_uint32_le(s, handle);
787
788 pUrb = proxy->pUrbs;
789
790 while (pUrb && pUrb->handle != handle)
791 {
792 pUrb = pUrb->pNext;
793 }
794
795 if (pUrb)
796 {
797 op_usbproxy_back_cancel_urb(proxy, pUrb);
798
799 /* No reply required. */
800
801 /* Remove URB from list. */
802 if (pUrb->pPrev)
803 {
804 pUrb->pPrev->pNext = pUrb->pNext;
805 }
806 else
807 {
808 proxy->pUrbs = pUrb->pNext;
809 }
810
811 if (pUrb->pNext)
812 {
813 pUrb->pNext->pPrev = pUrb->pPrev;
814 }
815
816 pUrb->pNext = pUrb->pPrev = NULL;
817
818 Log(("Cancelled URB %p\n", pUrb));
819
820 // xfree (pUrb);
821 }
822 } break;
823
824 case RDPUSB_REQ_DEVICE_LIST:
825 {
826 void *buf = NULL;
827 int len = 0;
828
829 buf = build_device_list (&len);
830
831 s = rdpusb_init_packet(len? len: 2, code);
832 if (len)
833 {
834 out_uint8p (s, buf, len);
835 }
836 else
837 {
838 out_uint16_le(s, 0);
839 }
840 s_mark_end(s);
841 rdpusb_send(s);
842
843 if (buf)
844 {
845 free (buf);
846 }
847 } break;
848
849 case RDPUSB_REQ_NEGOTIATE:
850 {
851 s = rdpusb_init_packet(1, code);
852 out_uint8(s, VRDP_USB_CAPS_FLAG_ASYNC);
853 s_mark_end(s);
854 rdpusb_send(s);
855 } break;
856
857 default:
858 unimpl("RDPUSB code %d\n", code);
859 break;
860 }
861}
862
863void
864rdpusb_add_fds(int *n, fd_set * rfds, fd_set * wfds)
865{
866 PUSBPROXYDEV proxy = g_proxies;
867
868// Log(("RDPUSB: rdpusb_add_fds: begin *n = %d\n", *n));
869
870 while (proxy)
871 {
872 int fd = USBProxyDeviceLinuxGetFD(proxy);
873
874 if (fd != -1)
875 {
876// Log(("RDPUSB: rdpusb_add_fds: adding %d\n", proxy->priv.File));
877
878 FD_SET(fd, rfds);
879 FD_SET(fd, wfds);
880 *n = MAX(*n, fd);
881 }
882
883 proxy = proxy->pNext;
884 }
885
886// Log(("RDPUSB: rdpusb_add_fds: end *n = %d\n", *n));
887
888 return;
889}
890
891void
892rdpusb_check_fds(fd_set * rfds, fd_set * wfds)
893{
894 PUSBPROXYDEV proxy = g_proxies;
895 unsigned found = 0;
896
897 while (proxy)
898 {
899 int fd = USBProxyDeviceLinuxGetFD(proxy);
900
901 if (fd != -1)
902 {
903 if (FD_ISSET(fd, rfds))
904 found = 1;
905 if (FD_ISSET(fd, wfds))
906 found = 1;
907 }
908
909 proxy = proxy->pNext;
910 }
911
912// Log(("RDPUSB: rdpusb_check_fds: begin\n"));
913
914 if (found)
915 rdpusb_reap_urbs ();
916
917// Log(("RDPUSB: rdpusb_check_fds: end\n"));
918
919 return;
920}
921
922
923RD_BOOL
924rdpusb_init(void)
925{
926 bool fUseUsbfs;
927 if (RT_SUCCESS(USBProxyLinuxChooseMethod(&fUseUsbfs, &g_pcszDevicesRoot)))
928 {
929 g_fUseSysfs = !fUseUsbfs;
930 rdpusb_channel =
931 channel_register("vrdpusb", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
932 rdpusb_process);
933 return (rdpusb_channel != NULL);
934 }
935 return false;
936}
937
938void
939rdpusb_close (void)
940{
941 PUSBPROXYDEV proxy = g_proxies;
942
943 while (proxy)
944 {
945 PUSBPROXYDEV pNext = proxy->pNext;
946
947 Log(("RDPUSB: closing proxy %p\n", proxy));
948
949 op_usbproxy_back_close(proxy);
950 xfree (proxy);
951
952 proxy = pNext;
953 }
954
955 return;
956}
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