VirtualBox

source: vbox/trunk/src/VBox/Main/RemoteUSBBackend.cpp@ 31891

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

Main: export USBProxyService and USBFilter to OSE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 36.6 KB
Line 
1/** @file
2 *
3 * VirtualBox Remote USB backend
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * Oracle Corporation confidential
10 * All rights reserved
11 */
12
13#define LOG_GROUP LOG_GROUP_DEV_USB
14#include "ConsoleImpl.h"
15#include "ConsoleVRDPServer.h"
16#include "RemoteUSBBackend.h"
17#include "RemoteUSBDeviceImpl.h"
18
19#include <VBox/vrdpapi.h>
20#include <VBox/vrdpusb.h>
21#include <VBox/err.h>
22#include <VBox/log.h>
23
24#include <VBox/vusb.h>
25
26#include <iprt/time.h>
27
28/** @page pg_vrdb_usb Async Remote USB
29 *
30 *
31 * USB backend functions are called in EMT so care must be taken to prevent
32 * delays in the functions execution.
33 *
34 * Among 11 backend functions 10 just return a success indicator.
35 *
36 * Such a function usually will check pending error code and if everything is ok,
37 * submit asynchronous RDP request and return success immediately.
38 *
39 * On actual completion of each request, the status will be saved as
40 * pending, so in case of an error all further functions will fail with
41 * device disconnected condition.
42 * @todo May be a device disconnect notification for console is required?
43 *
44 * The only remaining function that needs special processing is
45 * the reap_urb. It has a timeout parameter.
46 * Normally, the timeout is 0, as result of polling from VUSB frame timer.
47 * It is ok for async processing, the backend will periodically reap urbs from client.
48 * And already reaped URBs from client will be returned for the call.
49 * Exceptions:
50 * 1) during device initialization, when obtaining device descriptions
51 * the timeout is -1, and the request is expected to be processed synchronously.
52 * It looks like only 3 URBs with some information are retrieved that way.
53 * Probably, one can return this information in DEVICE_LIST together with the
54 * device description and when such request are submitted, just return
55 * the prefetched data.
56 * 2) during suspend timeout is non zero (10 or less milliseconds),
57 * and URB's are reaped for about 1 second. But here network delays
58 * will not affect the timeout, so it is ok.
59 *
60 *
61 * @subsection sub_vrdb_usb_dad Device attaching/detaching
62 *
63 * Devices are attached when client is connected or when a new device is connected to client.
64 * Devices are detached when client is disconnected (all devices) or a device is disconnected
65 * the client side.
66 *
67 * The backend polls the client for list of attached USB devices from RemoteUSBThread.
68 *
69 */
70
71/* Queued URB submitted to VRDP client. */
72typedef struct _REMOTEUSBQURB
73{
74 struct _REMOTEUSBQURB *next;
75 struct _REMOTEUSBQURB *prev;
76
77 PREMOTEUSBDEVICE pDevice; /* Device, the URB is queued for. */
78
79 uint32_t u32Handle; /* The handle of the URB. Generated by the Remote USB backend. */
80
81 void *pvData; /* Pointer to URB data allocated by VUSB. */
82 void *pvURB; /* Pointer to URB known to VUSB. */
83
84 uint32_t u32Len; /* Data length returned by the VRDP client. */
85 uint32_t u32Err; /* URB error code returned by the VRDP client. */
86
87 bool fCompleted; /* The URB has been returned back by VRDP client. */
88 bool fInput; /* This URB receives data from the client. */
89
90 uint32_t u32TransferredLen; /* For VRDP_USB_DIRECTION_OUT URBs = bytes written.
91 * For VRDP_USB_DIRECTION_IN URBs = bytes received.
92 */
93} REMOTEUSBQURB;
94
95/* Remote USB device instance data. */
96typedef struct _REMOTEUSBDEVICE
97{
98 struct _REMOTEUSBDEVICE *prev;
99 struct _REMOTEUSBDEVICE *next;
100
101 RemoteUSBBackend *pOwner;
102
103 VRDPUSBDEVID id; /* The remote identifier, assigned by client. */
104
105 uint32_t u32ClientId; /* The identifier of the remote client. */
106
107 REMOTEUSBQURB *pHeadQURBs; /* List of URBs queued for the device. */
108 REMOTEUSBQURB *pTailQURBs;
109
110 volatile uint32_t hURB; /* Source for URB's handles. */
111 bool fFailed; /* True if an operation has failed for the device. */
112 RTCRITSECT critsect; /* Protects the queued urb list. */
113} REMOTEUSBDEVICE;
114
115
116
117static void requestDevice(REMOTEUSBDEVICE *pDevice)
118{
119 int rc = RTCritSectEnter(&pDevice->critsect);
120 AssertRC(rc);
121}
122
123static void releaseDevice(REMOTEUSBDEVICE *pDevice)
124{
125 RTCritSectLeave(&pDevice->critsect);
126}
127
128static REMOTEUSBQURB *qurbAlloc(PREMOTEUSBDEVICE pDevice)
129{
130 /* @todo reuse URBs. */
131 REMOTEUSBQURB *pQURB = (REMOTEUSBQURB *)RTMemAllocZ (sizeof (REMOTEUSBQURB));
132
133 if (pQURB)
134 {
135 pQURB->pDevice = pDevice;
136 }
137
138 return pQURB;
139}
140
141static void qurbFree (REMOTEUSBQURB *pQURB)
142{
143 RTMemFree (pQURB);
144 return;
145}
146
147
148/* Called by VRDP server when the client responds to a request on USB channel. */
149DECLCALLBACK(int) USBClientResponseCallback (void *pv, uint32_t u32ClientId, uint8_t code, const void *pvRet, uint32_t cbRet)
150{
151 int rc = VINF_SUCCESS;
152
153 LogFlow(("USBClientResponseCallback: id = %d, pv = %p, code = %d, pvRet = %p, cbRet = %d\n",
154 u32ClientId, pv, code, pvRet, cbRet));
155
156 RemoteUSBBackend *pThis = (RemoteUSBBackend *)pv;
157
158 switch (code)
159 {
160 case VRDP_USB_REQ_DEVICE_LIST:
161 {
162 rc = pThis->saveDeviceList (pvRet, cbRet);
163 } break;
164
165 case VRDP_USB_REQ_NEGOTIATE:
166 {
167 if (pvRet && cbRet >= sizeof (VRDPUSBREQNEGOTIATERET))
168 {
169 VRDPUSBREQNEGOTIATERET *pret = (VRDPUSBREQNEGOTIATERET *)pvRet;
170
171 rc = pThis->negotiateResponse (pret, cbRet);
172 }
173 else
174 {
175 Log(("USBClientResponseCallback: WARNING: not enough data in response: pv = %p, cb = %d, expected %d.\n",
176 pvRet, cbRet, sizeof (VRDPUSBREQNEGOTIATERET)));
177
178 rc = VERR_INVALID_PARAMETER;
179 }
180 } break;
181
182 case VRDP_USB_REQ_REAP_URB:
183 {
184 rc = pThis->reapURB (pvRet, cbRet);
185
186 LogFlow(("USBClientResponseCallback: reap URB, rc = %Rrc.\n", rc));
187 } break;
188
189 case VRDP_USB_REQ_QUEUE_URB:
190 case VRDP_USB_REQ_CLOSE:
191 case VRDP_USB_REQ_CANCEL_URB:
192 {
193 /* Do nothing, actually this should not happen. */
194 Log(("USBClientResponseCallback: WARNING: response to a request %d is not expected!!!\n", code));
195 } break;
196
197 case VRDP_USB_REQ_OPEN:
198 case VRDP_USB_REQ_RESET:
199 case VRDP_USB_REQ_SET_CONFIG:
200 case VRDP_USB_REQ_CLAIM_INTERFACE:
201 case VRDP_USB_REQ_RELEASE_INTERFACE:
202 case VRDP_USB_REQ_INTERFACE_SETTING:
203 case VRDP_USB_REQ_CLEAR_HALTED_EP:
204 {
205 /*
206 * Device specific responses with status codes.
207 */
208 if (pvRet && cbRet >= sizeof (VRDPUSBREQRETHDR))
209 {
210 VRDPUSBREQRETHDR *pret = (VRDPUSBREQRETHDR *)pvRet;
211
212 if (pret->status != VRDP_USB_STATUS_SUCCESS)
213 {
214 REMOTEUSBDEVICE *pDevice = pThis->deviceFromId (pret->id);
215
216 if (!pDevice)
217 {
218 Log(("USBClientResponseCallback: WARNING: invalid device id %08X.\n", pret->id));
219 rc = VERR_INVALID_PARAMETER;
220 }
221 else
222 {
223 Log(("USBClientResponseCallback: WARNING: the operation failed, status %d\n", pret->status));
224 pDevice->fFailed = true;
225 }
226 }
227 }
228 else
229 {
230 Log(("USBClientResponseCallback: WARNING: not enough data in response: pv = %p, cb = %d, expected %d.\n",
231 pvRet, cbRet, sizeof (VRDPUSBREQRETHDR)));
232 }
233 } break;
234
235 default:
236 {
237 Log(("USBClientResponseCallback: WARNING: invalid code %d\n", code));
238 } break;
239 }
240
241 return rc;
242}
243
244/*
245 * Backend entry points.
246 */
247static DECLCALLBACK(int) iface_Open (PREMOTEUSBBACKEND pInstance, const char *pszAddress, size_t cbAddress, PREMOTEUSBDEVICE *ppDevice)
248{
249 int rc = VINF_SUCCESS;
250
251 RemoteUSBBackend *pThis = (RemoteUSBBackend *)pInstance;
252
253 REMOTEUSBDEVICE *pDevice = (REMOTEUSBDEVICE *)RTMemAllocZ (sizeof (REMOTEUSBDEVICE));
254
255 if (!pDevice)
256 {
257 rc = VERR_NO_MEMORY;
258 }
259 else
260 {
261 /* Parse given address string to find the device identifier.
262 * The format is "REMOTEUSB0xAAAABBBB&0xCCCCDDDD", where AAAABBBB is hex device identifier
263 * and CCCCDDDD is hex client id.
264 */
265 if (strncmp (pszAddress, REMOTE_USB_BACKEND_PREFIX_S, REMOTE_USB_BACKEND_PREFIX_LEN) != 0)
266 {
267 AssertFailed();
268 rc = VERR_INVALID_PARAMETER;
269 }
270 else
271 {
272 /* Initialize the device structure. */
273 pDevice->pOwner = pThis;
274
275 rc = RTCritSectInit(&pDevice->critsect);
276 AssertRC(rc);
277
278 if (RT_SUCCESS(rc))
279 {
280 pDevice->id = RTStrToUInt32 (&pszAddress[REMOTE_USB_BACKEND_PREFIX_LEN]);
281
282 size_t l = strlen (pszAddress);
283
284 if (l >= REMOTE_USB_BACKEND_PREFIX_LEN + strlen ("0x12345678&0x87654321"))
285 {
286 const char *p = &pszAddress[REMOTE_USB_BACKEND_PREFIX_LEN + strlen ("0x12345678")];
287 if (*p == '&')
288 {
289 pDevice->u32ClientId = RTStrToUInt32 (p + 1);
290 }
291 else
292 {
293 AssertFailed ();
294 rc = VERR_INVALID_PARAMETER;
295 }
296 }
297 else
298 {
299 AssertFailed ();
300 rc = VERR_INVALID_PARAMETER;
301 }
302
303 if (RT_SUCCESS(rc))
304 {
305 VRDP_USB_REQ_OPEN_PARM parm;
306
307 parm.code = VRDP_USB_REQ_OPEN;
308 parm.id = pDevice->id;
309
310 pThis->VRDPServer()->SendUSBRequest (pDevice->u32ClientId, &parm, sizeof (parm));
311 }
312 }
313 }
314 }
315
316 if (RT_SUCCESS(rc))
317 {
318 *ppDevice = pDevice;
319
320 pThis->addDevice (pDevice);
321 }
322 else
323 {
324 RTMemFree (pDevice);
325 }
326
327 return rc;
328}
329
330static DECLCALLBACK(void) iface_Close (PREMOTEUSBDEVICE pDevice)
331{
332 RemoteUSBBackend *pThis = pDevice->pOwner;
333
334 VRDP_USB_REQ_CLOSE_PARM parm;
335
336 parm.code = VRDP_USB_REQ_CLOSE;
337 parm.id = pDevice->id;
338
339 pThis->VRDPServer()->SendUSBRequest (pDevice->u32ClientId, &parm, sizeof (parm));
340
341 pThis->removeDevice (pDevice);
342
343 if (RTCritSectIsInitialized (&pDevice->critsect))
344 {
345 RTCritSectDelete (&pDevice->critsect);
346 }
347
348 RTMemFree (pDevice);
349
350 return;
351}
352
353static DECLCALLBACK(int) iface_Reset (PREMOTEUSBDEVICE pDevice)
354{
355 RemoteUSBBackend *pThis = pDevice->pOwner;
356
357 if (pDevice->fFailed)
358 {
359 return VERR_VUSB_DEVICE_NOT_ATTACHED;
360 }
361
362 VRDP_USB_REQ_RESET_PARM parm;
363
364 parm.code = VRDP_USB_REQ_RESET;
365 parm.id = pDevice->id;
366
367 pThis->VRDPServer()->SendUSBRequest (pDevice->u32ClientId, &parm, sizeof (parm));
368
369 return VINF_SUCCESS;
370}
371
372static DECLCALLBACK(int) iface_SetConfig (PREMOTEUSBDEVICE pDevice, uint8_t u8Cfg)
373{
374 RemoteUSBBackend *pThis = pDevice->pOwner;
375
376 if (pDevice->fFailed)
377 {
378 return VERR_VUSB_DEVICE_NOT_ATTACHED;
379 }
380
381 VRDP_USB_REQ_SET_CONFIG_PARM parm;
382
383 parm.code = VRDP_USB_REQ_SET_CONFIG;
384 parm.id = pDevice->id;
385 parm.configuration = u8Cfg;
386
387 pThis->VRDPServer()->SendUSBRequest (pDevice->u32ClientId, &parm, sizeof (parm));
388
389 return VINF_SUCCESS;
390}
391
392static DECLCALLBACK(int) iface_ClaimInterface (PREMOTEUSBDEVICE pDevice, uint8_t u8Ifnum)
393{
394 RemoteUSBBackend *pThis = pDevice->pOwner;
395
396 if (pDevice->fFailed)
397 {
398 return VERR_VUSB_DEVICE_NOT_ATTACHED;
399 }
400
401 VRDP_USB_REQ_CLAIM_INTERFACE_PARM parm;
402
403 parm.code = VRDP_USB_REQ_CLAIM_INTERFACE;
404 parm.id = pDevice->id;
405 parm.iface = u8Ifnum;
406
407 pThis->VRDPServer()->SendUSBRequest (pDevice->u32ClientId, &parm, sizeof (parm));
408
409 return VINF_SUCCESS;
410}
411
412static DECLCALLBACK(int) iface_ReleaseInterface (PREMOTEUSBDEVICE pDevice, uint8_t u8Ifnum)
413{
414 RemoteUSBBackend *pThis = pDevice->pOwner;
415
416 if (pDevice->fFailed)
417 {
418 return VERR_VUSB_DEVICE_NOT_ATTACHED;
419 }
420
421 VRDP_USB_REQ_RELEASE_INTERFACE_PARM parm;
422
423 parm.code = VRDP_USB_REQ_RELEASE_INTERFACE;
424 parm.id = pDevice->id;
425 parm.iface = u8Ifnum;
426
427 pThis->VRDPServer()->SendUSBRequest (pDevice->u32ClientId, &parm, sizeof (parm));
428
429 return VINF_SUCCESS;
430}
431
432static DECLCALLBACK(int) iface_InterfaceSetting (PREMOTEUSBDEVICE pDevice, uint8_t u8Ifnum, uint8_t u8Setting)
433{
434 RemoteUSBBackend *pThis = pDevice->pOwner;
435
436 if (pDevice->fFailed)
437 {
438 return VERR_VUSB_DEVICE_NOT_ATTACHED;
439 }
440
441 VRDP_USB_REQ_INTERFACE_SETTING_PARM parm;
442
443 parm.code = VRDP_USB_REQ_INTERFACE_SETTING;
444 parm.id = pDevice->id;
445 parm.iface = u8Ifnum;
446 parm.setting = u8Setting;
447
448 pThis->VRDPServer()->SendUSBRequest (pDevice->u32ClientId, &parm, sizeof (parm));
449
450 return VINF_SUCCESS;
451}
452
453static DECLCALLBACK(int) iface_ClearHaltedEP (PREMOTEUSBDEVICE pDevice, uint8_t u8Ep)
454{
455 RemoteUSBBackend *pThis = pDevice->pOwner;
456
457 if (pDevice->fFailed)
458 {
459 return VERR_VUSB_DEVICE_NOT_ATTACHED;
460 }
461
462 VRDP_USB_REQ_CLEAR_HALTED_EP_PARM parm;
463
464 parm.code = VRDP_USB_REQ_CLEAR_HALTED_EP;
465 parm.id = pDevice->id;
466 parm.ep = u8Ep;
467
468 pThis->VRDPServer()->SendUSBRequest (pDevice->u32ClientId, &parm, sizeof (parm));
469
470 return VINF_SUCCESS;
471}
472
473static DECLCALLBACK(void) iface_CancelURB (PREMOTEUSBDEVICE pDevice, PREMOTEUSBQURB pRemoteURB)
474{
475 RemoteUSBBackend *pThis = pDevice->pOwner;
476
477 VRDP_USB_REQ_CANCEL_URB_PARM parm;
478
479 parm.code = VRDP_USB_REQ_CANCEL_URB;
480 parm.id = pDevice->id;
481 parm.handle = pRemoteURB->u32Handle;
482
483 pThis->VRDPServer()->SendUSBRequest (pDevice->u32ClientId, &parm, sizeof (parm));
484
485 requestDevice (pDevice);
486
487 /* Remove this urb from the queue. It is safe because if
488 * client will return the URB, it will be just ignored
489 * in reapURB.
490 */
491 if (pRemoteURB->prev)
492 {
493 pRemoteURB->prev->next = pRemoteURB->next;
494 }
495 else
496 {
497 pDevice->pHeadQURBs = pRemoteURB->next;
498 }
499
500 if (pRemoteURB->next)
501 {
502 pRemoteURB->next->prev = pRemoteURB->prev;
503 }
504 else
505 {
506 pDevice->pTailQURBs = pRemoteURB->prev;
507 }
508
509 qurbFree (pRemoteURB);
510
511 releaseDevice (pDevice);
512
513 return;
514}
515
516static DECLCALLBACK(int) iface_QueueURB (PREMOTEUSBDEVICE pDevice, uint8_t u8Type, uint8_t u8Ep, uint8_t u8Direction, uint32_t u32Len, void *pvData, void *pvURB, PREMOTEUSBQURB *ppRemoteURB)
517{
518 int rc = VINF_SUCCESS;
519
520#ifdef DEBUG_sunlover
521 LogFlow(("RemoteUSBBackend::iface_QueueURB: u8Type = %d, u8Ep = %d, u8Direction = %d, data\n%.*Rhxd\n", u8Type, u8Ep, u8Direction, u32Len, pvData));
522#endif /* DEBUG_sunlover */
523
524 if (pDevice->fFailed)
525 {
526 return VERR_VUSB_DEVICE_NOT_ATTACHED;
527 }
528
529 RemoteUSBBackend *pThis = pDevice->pOwner;
530
531 VRDP_USB_REQ_QUEUE_URB_PARM parm;
532 uint32_t u32Handle = 0;
533 uint32_t u32DataLen = 0;
534
535 REMOTEUSBQURB *qurb = qurbAlloc (pDevice);
536
537 if (qurb == NULL)
538 {
539 rc = VERR_NO_MEMORY;
540 goto l_leave;
541 }
542
543 /*
544 * Compute length of data which need to be transferred to the client.
545 */
546 switch(u8Direction)
547 {
548 case VUSB_DIRECTION_IN:
549 {
550 if (u8Type == VUSBXFERTYPE_MSG)
551 {
552 u32DataLen = 8; /* 8 byte header. */
553 // u32DataLen = u32Len; // @todo do messages need all information?
554 }
555 } break;
556
557 case VUSB_DIRECTION_OUT:
558 {
559 u32DataLen = u32Len;
560 } break;
561
562 default:
563 {
564 AssertFailed();
565 rc = VERR_INVALID_PARAMETER;
566 goto l_leave;
567 }
568 }
569
570 parm.code = VRDP_USB_REQ_QUEUE_URB;
571 parm.id = pDevice->id;
572
573 u32Handle = pDevice->hURB++;
574 if (u32Handle == 0)
575 {
576 u32Handle = pDevice->hURB++;
577 }
578
579 LogFlow(("RemoteUSBBackend::iface_QueueURB: handle = %d\n", u32Handle));
580
581 parm.handle = u32Handle;
582
583 switch(u8Type)
584 {
585 case VUSBXFERTYPE_CTRL: parm.type = VRDP_USB_TRANSFER_TYPE_CTRL; break;
586 case VUSBXFERTYPE_ISOC: parm.type = VRDP_USB_TRANSFER_TYPE_ISOC; break;
587 case VUSBXFERTYPE_BULK: parm.type = VRDP_USB_TRANSFER_TYPE_BULK; break;
588 case VUSBXFERTYPE_INTR: parm.type = VRDP_USB_TRANSFER_TYPE_INTR; break;
589 case VUSBXFERTYPE_MSG: parm.type = VRDP_USB_TRANSFER_TYPE_MSG; break;
590 default: AssertFailed(); rc = VERR_INVALID_PARAMETER; goto l_leave;
591 }
592
593 parm.ep = u8Ep;
594
595 switch(u8Direction)
596 {
597 case VUSB_DIRECTION_SETUP: AssertFailed(); parm.direction = VRDP_USB_DIRECTION_SETUP; break;
598 case VUSB_DIRECTION_IN: parm.direction = VRDP_USB_DIRECTION_IN; break;
599 case VUSB_DIRECTION_OUT: parm.direction = VRDP_USB_DIRECTION_OUT; break;
600 default: AssertFailed(); rc = VERR_INVALID_PARAMETER; goto l_leave;
601 }
602
603 parm.urblen = u32Len;
604 parm.datalen = u32DataLen;
605
606 if (u32DataLen)
607 {
608 parm.data = pvData;
609 }
610
611 requestDevice (pDevice);
612
613 /* Add at tail of queued urb list. */
614 qurb->next = NULL;
615 qurb->prev = pDevice->pTailQURBs;
616 qurb->u32Err = VRDP_USB_XFER_OK;
617 qurb->u32Len = u32Len;
618 qurb->pvData = pvData;
619 qurb->pvURB = pvURB;
620 qurb->u32Handle = u32Handle;
621 qurb->fCompleted = false;
622 qurb->fInput = (u8Direction == VUSB_DIRECTION_IN);
623 qurb->u32TransferredLen = 0;
624
625 if (pDevice->pTailQURBs)
626 {
627 Assert(pDevice->pTailQURBs->next == NULL);
628 pDevice->pTailQURBs->next = qurb;
629 }
630 else
631 {
632 /* This is the first URB to be added. */
633 Assert(pDevice->pHeadQURBs == NULL);
634 pDevice->pHeadQURBs = qurb;
635 }
636
637 pDevice->pTailQURBs = qurb;
638
639 releaseDevice (pDevice);
640
641 *ppRemoteURB = qurb;
642
643 pThis->VRDPServer()->SendUSBRequest (pDevice->u32ClientId, &parm, sizeof (parm));
644
645l_leave:
646 if (RT_FAILURE(rc))
647 {
648 qurbFree (qurb);
649 }
650
651 return rc;
652}
653
654/* The function checks the URB queue for completed URBs. Also if the client
655 * has requested URB polling, the function will send URB poll requests.
656 */
657static DECLCALLBACK(int) iface_ReapURB (PREMOTEUSBDEVICE pDevice, uint32_t u32Millies, void **ppvURB, uint32_t *pu32Len, uint32_t *pu32Err)
658{
659 int rc = VINF_SUCCESS;
660
661 LogFlow(("RemoteUSBBackend::iface_ReapURB %d ms\n", u32Millies));
662
663 if (pDevice->fFailed)
664 {
665 return VERR_VUSB_DEVICE_NOT_ATTACHED;
666 }
667
668 RemoteUSBBackend *pThis = pDevice->pOwner;
669
670 /* Wait for transaction completion. */
671 uint64_t u64StartTime = RTTimeMilliTS ();
672
673 if (pThis->pollingEnabledURB ())
674 {
675 VRDP_USB_REQ_REAP_URB_PARM parm;
676
677 parm.code = VRDP_USB_REQ_REAP_URB;
678
679 pThis->VRDPServer()->SendUSBRequest (pDevice->u32ClientId, &parm, sizeof (parm));
680 }
681
682 REMOTEUSBQURB *qurb = NULL;
683
684 for (;;)
685 {
686 uint32_t u32ClientId;
687
688 /* Scan queued URBs, look for completed. */
689 requestDevice (pDevice);
690
691 u32ClientId = pDevice->u32ClientId;
692
693 qurb = pDevice->pHeadQURBs;
694
695 while (qurb)
696 {
697 if (qurb->fCompleted)
698 {
699 /* Remove this completed urb from the queue. */
700 if (qurb->prev)
701 {
702 qurb->prev->next = qurb->next;
703 }
704 else
705 {
706 pDevice->pHeadQURBs = qurb->next;
707 }
708
709 if (qurb->next)
710 {
711 qurb->next->prev = qurb->prev;
712 }
713 else
714 {
715 pDevice->pTailQURBs = qurb->prev;
716 }
717
718 qurb->next = NULL;
719 qurb->prev = NULL;
720
721 break;
722 }
723
724 qurb = qurb->next;
725 }
726
727 releaseDevice (pDevice);
728
729 if ( qurb
730 || !pDevice->pHeadQURBs
731 || u32Millies == 0
732 || pDevice->fFailed
733 || (RTTimeMilliTS () - u64StartTime >= (uint64_t)u32Millies))
734 {
735 /* Got an URB or do not have to wait for an URB. */
736 break;
737 }
738
739 LogFlow(("RemoteUSBBackend::iface_ReapURB iteration.\n"));
740
741 RTThreadSleep (10);
742
743 if (pThis->pollingEnabledURB ())
744 {
745 VRDP_USB_REQ_REAP_URB_PARM parm;
746
747 parm.code = VRDP_USB_REQ_REAP_URB;
748
749 pThis->VRDPServer()->SendUSBRequest (u32ClientId, &parm, sizeof (parm));
750 }
751 }
752
753 LogFlow(("RemoteUSBBackend::iface_ReapURB completed in %lld ms, qurb = %p\n", RTTimeMilliTS () - u64StartTime, qurb));
754
755 if (!qurb)
756 {
757 *ppvURB = NULL;
758 *pu32Len = 0;
759 *pu32Err = VUSBSTATUS_OK;
760 }
761 else
762 {
763 *ppvURB = qurb->pvURB;
764 *pu32Len = qurb->u32Len;
765 *pu32Err = qurb->u32Err;
766
767#ifdef LOG_ENABLED
768 Log(("URB len = %d, data = %p\n", qurb->u32Len, qurb->pvURB));
769 if (qurb->u32Len)
770 {
771 Log(("Received URB content:\n%.*Rhxd\n", qurb->u32Len, qurb->pvData));
772 }
773#endif
774
775 qurbFree (qurb);
776 }
777
778 return rc;
779}
780
781void RemoteUSBBackend::AddRef (void)
782{
783 cRefs++;
784}
785
786void RemoteUSBBackend::Release (void)
787{
788 cRefs--;
789
790 if (cRefs <= 0)
791 {
792 delete this;
793 }
794}
795
796void RemoteUSBBackend::PollRemoteDevices (void)
797{
798 if ( mfWillBeDeleted
799 && menmPollRemoteDevicesStatus != PollRemoteDevicesStatus_Dereferenced)
800 {
801 /* Unmount all remote USB devices. */
802 mConsole->processRemoteUSBDevices (mu32ClientId, NULL, 0);
803
804 menmPollRemoteDevicesStatus = PollRemoteDevicesStatus_Dereferenced;
805
806 Release ();
807
808 return;
809 }
810
811 switch (menmPollRemoteDevicesStatus)
812 {
813 case PollRemoteDevicesStatus_Negotiate:
814 {
815 VRDPUSBREQNEGOTIATEPARM parm;
816
817 parm.code = VRDP_USB_REQ_NEGOTIATE;
818 parm.version = VRDP_USB_VERSION;
819 parm.flags = 0;
820
821 mServer->SendUSBRequest (mu32ClientId, &parm, sizeof (parm));
822
823 /* Reference the object. When the client disconnects and
824 * the backend is about to be deleted, the method must be called
825 * to disconnect the USB devices (as stated above).
826 */
827 AddRef ();
828
829 /* Goto the disabled state. When a responce will be received
830 * the state will be changed to the SendRequest.
831 */
832 menmPollRemoteDevicesStatus = PollRemoteDevicesStatus_WaitNegotiateResponse;
833 } break;
834
835 case PollRemoteDevicesStatus_WaitNegotiateResponse:
836 {
837 LogFlow(("USB::PollRemoteDevices: WaitNegotiateResponse\n"));
838 /* Do nothing. */
839 } break;
840
841 case PollRemoteDevicesStatus_SendRequest:
842 {
843 LogFlow(("USB::PollRemoteDevices: SendRequest\n"));
844
845 /* Send a request for device list. */
846 VRDP_USB_REQ_DEVICE_LIST_PARM parm;
847
848 parm.code = VRDP_USB_REQ_DEVICE_LIST;
849
850 mServer->SendUSBRequest (mu32ClientId, &parm, sizeof (parm));
851
852 menmPollRemoteDevicesStatus = PollRemoteDevicesStatus_WaitResponse;
853 } break;
854
855 case PollRemoteDevicesStatus_WaitResponse:
856 {
857 LogFlow(("USB::PollRemoteDevices: WaitResponse\n"));
858
859 if (mfHasDeviceList)
860 {
861 mConsole->processRemoteUSBDevices (mu32ClientId, (VRDPUSBDEVICEDESC *)mpvDeviceList, mcbDeviceList);
862 LogFlow(("USB::PollRemoteDevices: WaitResponse after process\n"));
863
864 menmPollRemoteDevicesStatus = PollRemoteDevicesStatus_SendRequest;
865
866 mfHasDeviceList = false;
867 }
868 } break;
869
870 case PollRemoteDevicesStatus_Dereferenced:
871 {
872 LogFlow(("USB::PollRemoteDevices: Dereferenced\n"));
873 /* Do nothing. */
874 } break;
875
876 default:
877 {
878 AssertFailed ();
879 } break;
880 }
881}
882
883void RemoteUSBBackend::NotifyDelete (void)
884{
885 mfWillBeDeleted = true;
886}
887
888/*
889 * The backend maintains a list of UUIDs of devices
890 * which are managed by the backend.
891 */
892bool RemoteUSBBackend::addUUID (const Guid *pUuid)
893{
894 unsigned i;
895 for (i = 0; i < RT_ELEMENTS(aGuids); i++)
896 {
897 if (aGuids[i].isEmpty ())
898 {
899 aGuids[i] = *pUuid;
900 return true;
901 }
902 }
903
904 return false;
905}
906
907bool RemoteUSBBackend::findUUID (const Guid *pUuid)
908{
909 unsigned i;
910 for (i = 0; i < RT_ELEMENTS(aGuids); i++)
911 {
912 if (aGuids[i] == *pUuid)
913 {
914 return true;
915 }
916 }
917
918 return false;
919}
920
921void RemoteUSBBackend::removeUUID (const Guid *pUuid)
922{
923 unsigned i;
924 for (i = 0; i < RT_ELEMENTS(aGuids); i++)
925 {
926 if (aGuids[i] == *pUuid)
927 {
928 aGuids[i].clear ();
929 break;
930 }
931 }
932}
933
934RemoteUSBBackend::RemoteUSBBackend(Console *console, ConsoleVRDPServer *server, uint32_t u32ClientId)
935 :
936 mConsole (console),
937 mServer (server),
938 cRefs (0),
939 mu32ClientId (u32ClientId),
940 mfHasDeviceList (false),
941 mpvDeviceList (NULL),
942 mcbDeviceList (0),
943 menmPollRemoteDevicesStatus (PollRemoteDevicesStatus_Negotiate),
944 mfPollURB (true),
945 mpDevices (NULL),
946 mfWillBeDeleted (false),
947 mClientVersion (0) /* VRDP_USB_VERSION_2: the client version. */
948{
949 Assert(console);
950 Assert(server);
951
952 int rc = RTCritSectInit (&mCritsect);
953
954 if (RT_FAILURE(rc))
955 {
956 AssertFailed ();
957 memset (&mCritsect, 0, sizeof (mCritsect));
958 }
959
960 mCallback.pInstance = (PREMOTEUSBBACKEND)this;
961 mCallback.pfnOpen = iface_Open;
962 mCallback.pfnClose = iface_Close;
963 mCallback.pfnReset = iface_Reset;
964 mCallback.pfnSetConfig = iface_SetConfig;
965 mCallback.pfnClaimInterface = iface_ClaimInterface;
966 mCallback.pfnReleaseInterface = iface_ReleaseInterface;
967 mCallback.pfnInterfaceSetting = iface_InterfaceSetting;
968 mCallback.pfnQueueURB = iface_QueueURB;
969 mCallback.pfnReapURB = iface_ReapURB;
970 mCallback.pfnClearHaltedEP = iface_ClearHaltedEP;
971 mCallback.pfnCancelURB = iface_CancelURB;
972}
973
974RemoteUSBBackend::~RemoteUSBBackend()
975{
976 Assert(cRefs == 0);
977
978 if (RTCritSectIsInitialized (&mCritsect))
979 {
980 RTCritSectDelete (&mCritsect);
981 }
982
983 RTMemFree (mpvDeviceList);
984
985 mServer->usbBackendRemoveFromList (this);
986}
987
988int RemoteUSBBackend::negotiateResponse (const VRDPUSBREQNEGOTIATERET *pret, uint32_t cbRet)
989{
990 int rc = VINF_SUCCESS;
991
992 Log(("RemoteUSBBackend::negotiateResponse: flags = %02X.\n", pret->flags));
993
994 LogRel(("Remote USB: Received negotiate response. Flags 0x%02X.\n",
995 pret->flags));
996
997 if (pret->flags & VRDP_USB_CAPS_FLAG_POLL)
998 {
999 Log(("RemoteUSBBackend::negotiateResponse: client requested URB polling.\n"));
1000 mfPollURB = true;
1001 }
1002 else
1003 {
1004 mfPollURB = false;
1005 }
1006
1007 /* VRDP_USB_VERSION_2: check the client version. */
1008 if (pret->flags & VRDP_USB_CAPS2_FLAG_VERSION)
1009 {
1010 /* This could be a client version > 1. */
1011 if (cbRet >= sizeof (VRDPUSBREQNEGOTIATERET_2))
1012 {
1013 VRDPUSBREQNEGOTIATERET_2 *pret2 = (VRDPUSBREQNEGOTIATERET_2 *)pret;
1014
1015 if (pret2->u32Version <= VRDP_USB_VERSION)
1016 {
1017 /* This is OK. The client wants a version supported by the server. */
1018 mClientVersion = pret2->u32Version;
1019 }
1020 else
1021 {
1022 LogRel(("VRDP: ERROR: unsupported remote USB protocol client version %d.\n", pret2->u32Version));
1023 rc = VERR_NOT_SUPPORTED;
1024 }
1025 }
1026 else
1027 {
1028 LogRel(("VRDP: ERROR: invalid remote USB negotiate request packet size %d.\n", cbRet));
1029 rc = VERR_NOT_SUPPORTED;
1030 }
1031 }
1032 else
1033 {
1034 /* This is a client version 1. */
1035 mClientVersion = VRDP_USB_VERSION_1;
1036 }
1037
1038 if (RT_SUCCESS(rc))
1039 {
1040 LogRel(("VRDP: remote USB protocol version %d.\n", mClientVersion));
1041
1042 menmPollRemoteDevicesStatus = PollRemoteDevicesStatus_SendRequest;
1043 }
1044
1045 return rc;
1046}
1047
1048int RemoteUSBBackend::saveDeviceList (const void *pvList, uint32_t cbList)
1049{
1050 Log(("RemoteUSBBackend::saveDeviceList: pvList = %p, cbList = %d\n", pvList, cbList));
1051
1052 if (!mfHasDeviceList)
1053 {
1054 RTMemFree (mpvDeviceList);
1055 mpvDeviceList = NULL;
1056
1057 mcbDeviceList = cbList;
1058
1059 if (cbList > 0)
1060 {
1061 mpvDeviceList = RTMemAlloc (cbList);
1062 memcpy (mpvDeviceList, pvList, cbList);
1063 }
1064
1065 mfHasDeviceList = true;
1066 }
1067
1068 return VINF_SUCCESS;
1069}
1070
1071void RemoteUSBBackend::request (void)
1072{
1073 int rc = RTCritSectEnter(&mCritsect);
1074 AssertRC(rc);
1075}
1076
1077void RemoteUSBBackend::release (void)
1078{
1079 RTCritSectLeave(&mCritsect);
1080}
1081
1082PREMOTEUSBDEVICE RemoteUSBBackend::deviceFromId (VRDPUSBDEVID id)
1083{
1084 request ();
1085
1086 REMOTEUSBDEVICE *pDevice = mpDevices;
1087
1088 while (pDevice && pDevice->id != id)
1089 {
1090 pDevice = pDevice->next;
1091 }
1092
1093 release ();
1094
1095 return pDevice;
1096}
1097
1098void RemoteUSBBackend::addDevice (PREMOTEUSBDEVICE pDevice)
1099{
1100 request ();
1101
1102 pDevice->next = mpDevices;
1103
1104 if (mpDevices)
1105 {
1106 mpDevices->prev = pDevice;
1107 }
1108
1109 mpDevices = pDevice;
1110
1111 release ();
1112}
1113
1114void RemoteUSBBackend::removeDevice (PREMOTEUSBDEVICE pDevice)
1115{
1116 request ();
1117
1118 if (pDevice->prev)
1119 {
1120 pDevice->prev->next = pDevice->next;
1121 }
1122 else
1123 {
1124 mpDevices = pDevice->next;
1125 }
1126
1127 if (pDevice->next)
1128 {
1129 pDevice->next->prev = pDevice->prev;
1130 }
1131
1132 release ();
1133}
1134
1135int RemoteUSBBackend::reapURB (const void *pvBody, uint32_t cbBody)
1136{
1137 int rc = VINF_SUCCESS;
1138
1139 LogFlow(("RemoteUSBBackend::reapURB: pvBody = %p, cbBody = %d\n", pvBody, cbBody));
1140
1141 VRDPUSBREQREAPURBBODY *pBody = (VRDPUSBREQREAPURBBODY *)pvBody;
1142
1143 while (cbBody >= sizeof (VRDPUSBREQREAPURBBODY))
1144 {
1145 Log(("RemoteUSBBackend::reapURB: id = %d, flags = %02X, error = %d, handle %d, len = %d.\n",
1146 pBody->id, pBody->flags, pBody->error, pBody->handle, pBody->len));
1147
1148 uint8_t fu8ReapValidFlags;
1149
1150 if (mClientVersion == VRDP_USB_VERSION_1 || mClientVersion == VRDP_USB_VERSION_2)
1151 {
1152 fu8ReapValidFlags = VRDP_USB_REAP_VALID_FLAGS;
1153 }
1154 else
1155 {
1156 fu8ReapValidFlags = VRDP_USB_REAP_VALID_FLAGS_3;
1157 }
1158
1159 /* Verify client's data. */
1160 if ( (pBody->flags & ~fu8ReapValidFlags) != 0
1161 || sizeof (VRDPUSBREQREAPURBBODY) > cbBody
1162 || pBody->handle == 0)
1163 {
1164 LogFlow(("RemoteUSBBackend::reapURB: WARNING: invalid reply data. Skipping the reply.\n"));
1165 rc = VERR_INVALID_PARAMETER;
1166 break;
1167 }
1168
1169 PREMOTEUSBDEVICE pDevice = deviceFromId (pBody->id);
1170
1171 if (!pDevice)
1172 {
1173 LogFlow(("RemoteUSBBackend::reapURB: WARNING: invalid device id. Skipping the reply.\n"));
1174 rc = VERR_INVALID_PARAMETER;
1175 break;
1176 }
1177
1178 uint32_t cbBodyData = 0; /* Data contained in the URB body structure for input URBs. */
1179
1180 requestDevice (pDevice);
1181
1182 /* Search the queued URB for given handle. */
1183 REMOTEUSBQURB *qurb = pDevice->pHeadQURBs;
1184
1185 while (qurb && qurb->u32Handle != pBody->handle)
1186 {
1187 LogFlow(("RemoteUSBBackend::reapURB: searching: %p handle = %d.\n", qurb, qurb->u32Handle));
1188 qurb = qurb->next;
1189 }
1190
1191 if (!qurb)
1192 {
1193 LogFlow(("RemoteUSBBackend::reapURB: Queued URB not found, probably already canceled. Skipping the URB.\n"));
1194 }
1195 else
1196 {
1197 LogFlow(("RemoteUSBBackend::reapURB: qurb = %p\n", qurb));
1198
1199 /* Update the URB error field. */
1200 if (mClientVersion == VRDP_USB_VERSION_1)
1201 {
1202 switch(pBody->error)
1203 {
1204 case VRDP_USB_XFER_OK: qurb->u32Err = VUSBSTATUS_OK; break;
1205 case VRDP_USB_XFER_STALL: qurb->u32Err = VUSBSTATUS_STALL; break;
1206 case VRDP_USB_XFER_DNR: qurb->u32Err = VUSBSTATUS_DNR; break;
1207 case VRDP_USB_XFER_CRC: qurb->u32Err = VUSBSTATUS_CRC; break;
1208 default: Log(("RemoteUSBBackend::reapURB: Invalid error %d\n", pBody->error));
1209 qurb->u32Err = VUSBSTATUS_DNR; break;
1210 }
1211 }
1212 else if ( mClientVersion == VRDP_USB_VERSION_2
1213 || mClientVersion == VRDP_USB_VERSION_3)
1214 {
1215 switch(pBody->error)
1216 {
1217 case VRDP_USB_XFER_OK: qurb->u32Err = VUSBSTATUS_OK; break;
1218 case VRDP_USB_XFER_STALL: qurb->u32Err = VUSBSTATUS_STALL; break;
1219 case VRDP_USB_XFER_DNR: qurb->u32Err = VUSBSTATUS_DNR; break;
1220 case VRDP_USB_XFER_CRC: qurb->u32Err = VUSBSTATUS_CRC; break;
1221 case VRDP_USB_XFER_DO: qurb->u32Err = VUSBSTATUS_DATA_OVERRUN; break;
1222 case VRDP_USB_XFER_DU: qurb->u32Err = VUSBSTATUS_DATA_UNDERRUN; break;
1223
1224 /* Unmapped errors. */
1225 case VRDP_USB_XFER_BS:
1226 case VRDP_USB_XFER_DTM:
1227 case VRDP_USB_XFER_PCF:
1228 case VRDP_USB_XFER_UPID:
1229 case VRDP_USB_XFER_BO:
1230 case VRDP_USB_XFER_BU:
1231 case VRDP_USB_XFER_ERR:
1232 default: Log(("RemoteUSBBackend::reapURB: Invalid error %d\n", pBody->error));
1233 qurb->u32Err = VUSBSTATUS_DNR; break;
1234 }
1235 }
1236 else
1237 {
1238 qurb->u32Err = VUSBSTATUS_DNR;
1239 }
1240
1241 /* Get the URB data. */
1242 bool fURBCompleted = true;
1243
1244 if (qurb->fInput)
1245 {
1246 cbBodyData = pBody->len; /* VRDP_USB_DIRECTION_IN URBs include some data. */
1247 }
1248
1249 if ( qurb->u32Err == VUSBSTATUS_OK
1250 && qurb->fInput)
1251 {
1252 LogFlow(("RemoteUSBBackend::reapURB: copying data %d bytes\n", pBody->len));
1253
1254 uint32_t u32DataLen = qurb->u32TransferredLen + pBody->len;
1255
1256 if (u32DataLen > qurb->u32Len)
1257 {
1258 /* Received more data than expected for this URB. If there more fragments follow,
1259 * they will be discarded because the URB handle will not be valid anymore.
1260 */
1261 qurb->u32Err = VUSBSTATUS_DNR;
1262 }
1263 else
1264 {
1265 memcpy ((uint8_t *)qurb->pvData + qurb->u32TransferredLen, &pBody[1], pBody->len);
1266 }
1267
1268 if ( qurb->u32Err == VUSBSTATUS_OK
1269 && (pBody->flags & VRDP_USB_REAP_FLAG_FRAGMENT) != 0)
1270 {
1271 /* If the client sends fragmented packets, accumulate the URB data. */
1272 fURBCompleted = false;
1273 }
1274 }
1275
1276 qurb->u32TransferredLen += pBody->len; /* Update the value for all URBs. */
1277
1278 if (fURBCompleted)
1279 {
1280 /* Move the URB to head of URB list, so the iface_ReapURB could find it faster. */
1281 if (qurb->prev)
1282 {
1283 /* The URB is not in the head. */
1284 qurb->prev->next = qurb->next;
1285
1286 if (qurb->next)
1287 {
1288 qurb->next->prev = qurb->prev;
1289 }
1290 else
1291 {
1292 pDevice->pTailQURBs = qurb->prev;
1293 }
1294
1295 qurb->next = pDevice->pHeadQURBs;
1296 qurb->prev = NULL;
1297
1298 pDevice->pHeadQURBs->prev = qurb;
1299 pDevice->pHeadQURBs = qurb;
1300 }
1301
1302 qurb->u32Len = qurb->u32TransferredLen; /* Update the final length. */
1303 qurb->fCompleted = true;
1304 }
1305 }
1306
1307 releaseDevice (pDevice);
1308
1309 if (pBody->flags & VRDP_USB_REAP_FLAG_LAST)
1310 {
1311 break;
1312 }
1313
1314 /* There is probably a further URB body. */
1315 uint32_t cbBodySize = sizeof (VRDPUSBREQREAPURBBODY) + cbBodyData;
1316
1317 if (cbBodySize > cbBody)
1318 {
1319 rc = VERR_INVALID_PARAMETER;
1320 break;
1321 }
1322
1323 pBody = (VRDPUSBREQREAPURBBODY *)((uint8_t *)pBody + cbBodySize);
1324 cbBody -= cbBodySize;
1325 }
1326
1327 LogFlow(("RemoteUSBBackend::reapURB: returns %Rrc\n", rc));
1328
1329 return rc;
1330}
1331/* vi: set tabstop=4 shiftwidth=4 expandtab: */
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