VirtualBox

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

Last change on this file since 36119 was 36119, checked in by vboxsync, 14 years ago

RDP/client: fix some warnings

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