VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.4/vrdp/rdpusb.c@ 94343

Last change on this file since 94343 was 94343, checked in by vboxsync, 3 years ago

Main,VMM/PDMUsb,Devices/USB,VRDP: Drop passing pointers through CFGM in favor of using VMM2USERMETHODS::pfnQueryGenericObject, bugref:10053 [build fix]

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