VirtualBox

source: vbox/trunk/src/VBox/Main/src-client/RemoteUSBBackend.cpp

Last change on this file was 100521, checked in by vboxsync, 10 months ago

Main: separate function for parsing the entries in remote USB device list. bugref:10478

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

© 2023 Oracle
ContactPrivacy policyTerms of Use