VirtualBox

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

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

OSE header fixes

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