VirtualBox

source: vbox/trunk/src/VBox/Devices/USB/VUSBInternal.h@ 104804

Last change on this file since 104804 was 104804, checked in by vboxsync, 4 months ago

Devices/USB: Fix a deadlock in OHCI triggered when saving the current
state of a VM or taking a snapshot. bugref:10692 ticketref:22059

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.4 KB
Line 
1/* $Id: VUSBInternal.h 104804 2024-05-28 13:04:36Z vboxsync $ */
2/** @file
3 * Virtual USB - Internal header.
4 *
5 * This subsystem implements USB devices in a host controller independent
6 * way. All the host controller code has to do is use VUSBROOTHUB for its
7 * root hub implementation and any emulated USB device may be plugged into
8 * the virtual bus.
9 */
10
11/*
12 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
13 *
14 * This file is part of VirtualBox base platform packages, as
15 * available from https://www.virtualbox.org.
16 *
17 * This program is free software; you can redistribute it and/or
18 * modify it under the terms of the GNU General Public License
19 * as published by the Free Software Foundation, in version 3 of the
20 * License.
21 *
22 * This program is distributed in the hope that it will be useful, but
23 * WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 * General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, see <https://www.gnu.org/licenses>.
29 *
30 * SPDX-License-Identifier: GPL-3.0-only
31 */
32
33#ifndef VBOX_INCLUDED_SRC_USB_VUSBInternal_h
34#define VBOX_INCLUDED_SRC_USB_VUSBInternal_h
35#ifndef RT_WITHOUT_PRAGMA_ONCE
36# pragma once
37#endif
38
39#include <VBox/cdefs.h>
40#include <VBox/types.h>
41#include <VBox/vusb.h>
42#include <VBox/vmm/stam.h>
43#include <VBox/vmm/pdm.h>
44#include <VBox/vmm/vmapi.h>
45#include <VBox/vmm/pdmusb.h>
46#include <iprt/asm.h>
47#include <iprt/assert.h>
48#include <iprt/req.h>
49#include <iprt/asm.h>
50#include <iprt/list.h>
51
52#include "VUSBSniffer.h"
53
54RT_C_DECLS_BEGIN
55
56
57/** @defgroup grp_vusb_int VUSB Internals.
58 * @ingroup grp_vusb
59 * @internal
60 * @{
61 */
62
63/** @defgroup grp_vusb_int_dev Internal Device Operations, Structures and Constants.
64 * @{
65 */
66
67/** Pointer to a Virtual USB device (core). */
68typedef struct VUSBDEV *PVUSBDEV;
69/** Pointer to a VUSB root hub. */
70typedef struct VUSBROOTHUB *PVUSBROOTHUB;
71
72
73/** Number of the default control endpoint */
74#define VUSB_PIPE_DEFAULT 0
75
76/** @name Device addresses
77 * @{ */
78#define VUSB_DEFAULT_ADDRESS 0
79#define VUSB_INVALID_ADDRESS UINT8_C(0xff)
80#define VUSB_ADDRESS_MASK UINT8_C(0x7f)
81/** @} */
82
83/** @name Feature bits (1<<FEATURE for the u16Status bit)
84 * @{ */
85#define VUSB_DEV_SELF_POWERED 0
86#define VUSB_DEV_REMOTE_WAKEUP 1
87#define VUSB_EP_HALT 0
88/** @} */
89
90/** Maximum number of endpoint addresses */
91#define VUSB_PIPE_MAX 16
92
93/**
94 * The VUSB URB data.
95 */
96typedef struct VUSBURBVUSBINT
97{
98 /** Node for one of the lists the URB can be in. */
99 RTLISTNODE NdLst;
100 /** Pointer to the URB this structure is part of. */
101 PVUSBURB pUrb;
102 /** Pointer to the original for control messages. */
103 PVUSBURB pCtrlUrb;
104 /** Pointer to the VUSB device.
105 * This may be NULL if the destination address is invalid. */
106 PVUSBDEV pDev;
107 /** Specific to the pfnFree function. */
108 void *pvFreeCtx;
109 /**
110 * Callback which will free the URB once it's reaped and completed.
111 * @param pUrb The URB.
112 */
113 DECLCALLBACKMEMBER(void, pfnFree,(PVUSBURB pUrb));
114 /** Submit timestamp. (logging only) */
115 uint64_t u64SubmitTS;
116} VUSBURBVUSBINT;
117
118/**
119 * Control-pipe stages.
120 */
121typedef enum CTLSTAGE
122{
123 /** the control pipe is in the setup stage. */
124 CTLSTAGE_SETUP = 0,
125 /** the control pipe is in the data stage. */
126 CTLSTAGE_DATA,
127 /** the control pipe is in the status stage. */
128 CTLSTAGE_STATUS
129} CTLSTAGE;
130
131/**
132 * Extra data for a control pipe.
133 *
134 * This is state information needed for the special multi-stage
135 * transfers performed on this kind of pipes.
136 */
137typedef struct vusb_ctrl_extra
138{
139 /** Current pipe stage. */
140 CTLSTAGE enmStage;
141 /** Success indicator. */
142 bool fOk;
143 /** Set if the message URB has been submitted. */
144 bool fSubmitted;
145 /** Pointer to the SETUP.
146 * This is a pointer to Urb->abData[0]. */
147 PVUSBSETUP pMsg;
148 /** Current DATA pointer.
149 * This starts at pMsg + 1 and is incremented at we read/write data. */
150 uint8_t *pbCur;
151 /** The amount of data left to read on IN operations.
152 * On OUT operations this is not used. */
153 uint32_t cbLeft;
154 /** The amount of data we can house.
155 * This starts at the default 8KB, and this structure will be reallocated to
156 * accommodate any larger request (unlikely). */
157 uint32_t cbMax;
158 /** VUSB internal data for the extra URB. */
159 VUSBURBVUSBINT VUsbExtra;
160 /** The message URB. */
161 VUSBURB Urb;
162} VUSBCTRLEXTRA, *PVUSBCTRLEXTRA;
163
164void vusbMsgFreeExtraData(PVUSBCTRLEXTRA pExtra);
165void vusbMsgResetExtraData(PVUSBCTRLEXTRA pExtra);
166
167/**
168 * A VUSB pipe
169 */
170typedef struct vusb_pipe
171{
172 PCVUSBDESCENDPOINTEX in;
173 PCVUSBDESCENDPOINTEX out;
174 /** Pointer to the extra state data required to run a control pipe. */
175 PVUSBCTRLEXTRA pCtrl;
176 /** Critical section serializing access to the extra state data for a control pipe. */
177 RTCRITSECT CritSectCtrl;
178 /** Count of active async transfers. */
179 volatile uint32_t async;
180 /** Last scheduled frame - only valid for isochronous IN endpoints. */
181 uint32_t uLastFrameIn;
182 /** Last scheduled frame - only valid for isochronous OUT endpoints. */
183 uint32_t uLastFrameOut;
184} VUSBPIPE;
185/** Pointer to a VUSB pipe structure. */
186typedef VUSBPIPE *PVUSBPIPE;
187
188
189/**
190 * Interface state and possible settings.
191 */
192typedef struct vusb_interface_state
193{
194 /** Pointer to the interface descriptor of the currently selected (active)
195 * interface. */
196 PCVUSBDESCINTERFACEEX pCurIfDesc;
197 /** Pointer to the interface settings. */
198 PCVUSBINTERFACE pIf;
199} VUSBINTERFACESTATE;
200/** Pointer to interface state. */
201typedef VUSBINTERFACESTATE *PVUSBINTERFACESTATE;
202/** Pointer to const interface state. */
203typedef const VUSBINTERFACESTATE *PCVUSBINTERFACESTATE;
204
205
206/**
207 * VUSB URB pool.
208 */
209typedef struct VUSBURBPOOL
210{
211 /** Critical section protecting the pool. */
212 RTCRITSECT CritSectPool;
213 /** Chain of free URBs by type. (Singly linked) */
214 RTLISTANCHOR aLstFreeUrbs[VUSBXFERTYPE_ELEMENTS];
215 /** The number of URBs in the pool. */
216 volatile uint32_t cUrbsInPool;
217 /** Align the size to a 8 byte boundary. */
218 uint32_t Alignment0;
219} VUSBURBPOOL;
220/** Pointer to a VUSB URB pool. */
221typedef VUSBURBPOOL *PVUSBURBPOOL;
222
223AssertCompileSizeAlignment(VUSBURBPOOL, 8);
224
225/**
226 * A Virtual USB device (core).
227 *
228 * @implements VUSBIDEVICE
229 */
230typedef struct VUSBDEV
231{
232 /** The device interface exposed to the HCI. */
233 VUSBIDEVICE IDevice;
234 /** Pointer to the PDM USB device instance. */
235 PPDMUSBINS pUsbIns;
236 /** Pointer to the roothub this device is attached to. */
237 PVUSBROOTHUB pHub;
238 /** The device state. */
239 VUSBDEVICESTATE volatile enmState;
240 /** Reference counter to protect the device structure from going away. */
241 uint32_t volatile cRefs;
242
243 /** The device address. */
244 uint8_t u8Address;
245 /** The new device address. */
246 uint8_t u8NewAddress;
247 /** The port. */
248 int16_t i16Port;
249 /** Device status. (VUSB_DEV_SELF_POWERED or not.) */
250 uint16_t u16Status;
251
252 /** Pointer to the descriptor cache.
253 * (Provided by the device thru the pfnGetDescriptorCache method.) */
254 PCPDMUSBDESCCACHE pDescCache;
255 /** Current configuration. */
256 PCVUSBDESCCONFIGEX pCurCfgDesc;
257
258 /** Current interface state (including alternate interface setting) - maximum
259 * valid index is config->bNumInterfaces
260 */
261 PVUSBINTERFACESTATE paIfStates;
262
263 /** Pipe/direction -> endpoint descriptor mapping */
264 VUSBPIPE aPipes[VUSB_PIPE_MAX];
265 /** Critical section protecting the active URB list. */
266 RTCRITSECT CritSectAsyncUrbs;
267 /** List of active async URBs. */
268 RTLISTANCHOR LstAsyncUrbs;
269
270 /** Dumper state. */
271 union VUSBDEVURBDUMPERSTATE
272 {
273 /** The current scsi command. */
274 uint8_t u8ScsiCmd;
275 } Urb;
276
277 /** The reset timer handle. */
278 TMTIMERHANDLE hResetTimer;
279 /** Reset handler arguments. */
280 void *pvArgs;
281 /** URB submit and reap thread. */
282 RTTHREAD hUrbIoThread;
283 /** Request queue for executing tasks on the I/O thread which should be done
284 * synchronous and without any other thread accessing the USB device. */
285 RTREQQUEUE hReqQueueSync;
286 /** Sniffer instance for this device if configured. */
287 VUSBSNIFFER hSniffer;
288 /** Flag whether the URB I/O thread should terminate. */
289 bool volatile fTerminate;
290 /** Flag whether the I/O thread was woken up. */
291 bool volatile fWokenUp;
292#if HC_ARCH_BITS == 32
293 /** Align the size to a 8 byte boundary. */
294 bool afAlignment0[2];
295#endif
296 /** The pool of free URBs for faster allocation. */
297 VUSBURBPOOL UrbPool;
298} VUSBDEV;
299AssertCompileSizeAlignment(VUSBDEV, 8);
300
301
302int vusbDevInit(PVUSBDEV pDev, PPDMUSBINS pUsbIns, const char *pszCaptureFilename);
303void vusbDevDestroy(PVUSBDEV pDev);
304bool vusbDevDoSelectConfig(PVUSBDEV dev, PCVUSBDESCCONFIGEX pCfg);
305void vusbDevMapEndpoint(PVUSBDEV dev, PCVUSBDESCENDPOINTEX ep);
306int vusbDevDetach(PVUSBDEV pDev);
307int vusbDevAttach(PVUSBDEV pDev, PVUSBROOTHUB pHub);
308DECLINLINE(PVUSBROOTHUB) vusbDevGetRh(PVUSBDEV pDev);
309size_t vusbDevMaxInterfaces(PVUSBDEV dev);
310
311void vusbDevSetAddress(PVUSBDEV pDev, uint8_t u8Address);
312bool vusbDevStandardRequest(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, void *pvBuf, uint32_t *pcbBuf);
313
314
315/** @} */
316
317
318/** @defgroup grp_vusb_int_hub Internal Hub Operations, Structures and Constants.
319 * @{
320 */
321
322
323/** @} */
324
325
326/** @defgroup grp_vusb_int_roothub Internal Root Hub Operations, Structures and Constants.
327 * @{
328 */
329
330/**
331 * Per transfer type statistics.
332 */
333typedef struct VUSBROOTHUBTYPESTATS
334{
335 STAMCOUNTER StatUrbsSubmitted;
336 STAMCOUNTER StatUrbsFailed;
337 STAMCOUNTER StatUrbsCancelled;
338
339 STAMCOUNTER StatReqBytes;
340 STAMCOUNTER StatReqReadBytes;
341 STAMCOUNTER StatReqWriteBytes;
342
343 STAMCOUNTER StatActBytes;
344 STAMCOUNTER StatActReadBytes;
345 STAMCOUNTER StatActWriteBytes;
346} VUSBROOTHUBTYPESTATS, *PVUSBROOTHUBTYPESTATS;
347
348
349
350/** Pointer to a VUSBROOTHUBLOAD struct. */
351typedef struct VUSBROOTHUBLOAD *PVUSBROOTHUBLOAD;
352
353/**
354 * The instance data of a root hub driver.
355 *
356 * This extends the generic VUSB hub.
357 *
358 * @implements VUSBIROOTHUBCONNECTOR
359 */
360typedef struct VUSBROOTHUB
361{
362 /** Pointer to the driver instance. */
363 PPDMDRVINS pDrvIns;
364 /** Pointer to the root hub port interface we're attached to. */
365 PVUSBIROOTHUBPORT pIRhPort;
366 /** Connector interface exposed upwards. */
367 VUSBIROOTHUBCONNECTOR IRhConnector;
368
369 /** Critical section protecting the device arrays. */
370 RTCRITSECT CritSectDevices;
371 /** Array of pointers to USB devices indexed by the port the device is on. */
372 PVUSBDEV apDevByPort[VUSB_DEVICES_MAX];
373 /** Array of pointers to USB devices indexed by the address assigned. */
374 PVUSBDEV apDevByAddr[VUSB_DEVICES_MAX];
375 /** Structure after a saved state load to re-attach devices. */
376 PVUSBROOTHUBLOAD pLoad;
377
378 /** Roothub device state. */
379 VUSBDEVICESTATE enmState;
380 /** Number of ports this roothub offers. */
381 uint16_t cPorts;
382 /** Number of devices attached to this roothub currently. */
383 uint16_t cDevices;
384 /** Name of the roothub. Used for logging. */
385 char *pszName;
386 /** URB pool for URBs from the roothub. */
387 VUSBURBPOOL UrbPool;
388
389#if HC_ARCH_BITS == 32
390 uint32_t Alignment0;
391#endif
392
393 /** Availability Bitmap. */
394 VUSBPORTBITMAP Bitmap;
395
396 /** Sniffer instance for the root hub. */
397 VUSBSNIFFER hSniffer;
398 /** Version of the attached Host Controller. */
399 uint32_t fHcVersions;
400 /** Size of the HCI specific data for each URB. */
401 size_t cbHci;
402 /** Size of the HCI specific TD. */
403 size_t cbHciTd;
404
405 /** The periodic frame processing thread. */
406 R3PTRTYPE(PPDMTHREAD) hThreadPeriodFrame;
407 /** Event semaphore to interact with the periodic frame processing thread. */
408 R3PTRTYPE(RTSEMEVENTMULTI) hSemEventPeriodFrame;
409 /** Event semaphore to release the thread waiting for the periodic frame processing thread to stop. */
410 R3PTRTYPE(RTSEMEVENTMULTI) hSemEventPeriodFrameStopped;
411 /** Current default frame rate for periodic frame processing thread. */
412 volatile uint32_t uFrameRateDefault;
413 /** Current frame rate (can be lower than the default frame rate if there is no activity). */
414 uint32_t uFrameRate;
415 /** How long to wait until the next frame. */
416 uint64_t nsWait;
417 /** Timestamp when the last frame was processed. */
418 uint64_t tsFrameProcessed;
419 /** Number of USB work cycles with no transfers. */
420 uint32_t cIdleCycles;
421
422 /** Flag whether a frame is currently being processed. */
423 volatile bool fFrameProcessing;
424 /** Flag whether we are in the middle of saving the VM state. */
425 volatile bool fSavingState;
426
427#if HC_ARCH_BITS == 32
428 uint32_t Alignment1;
429#endif
430
431#ifdef LOG_ENABLED
432 /** A serial number for URBs submitted on the roothub instance.
433 * Only logging builds. */
434 uint32_t iSerial;
435 /** Alignment */
436 uint32_t Alignment2;
437#endif
438#ifdef VBOX_WITH_STATISTICS
439 VUSBROOTHUBTYPESTATS Total;
440 VUSBROOTHUBTYPESTATS aTypes[VUSBXFERTYPE_MSG];
441 STAMCOUNTER StatIsocReqPkts;
442 STAMCOUNTER StatIsocReqReadPkts;
443 STAMCOUNTER StatIsocReqWritePkts;
444 STAMCOUNTER StatIsocActPkts;
445 STAMCOUNTER StatIsocActReadPkts;
446 STAMCOUNTER StatIsocActWritePkts;
447 struct
448 {
449 STAMCOUNTER Pkts;
450 STAMCOUNTER Ok;
451 STAMCOUNTER Ok0;
452 STAMCOUNTER DataUnderrun;
453 STAMCOUNTER DataUnderrun0;
454 STAMCOUNTER DataOverrun;
455 STAMCOUNTER NotAccessed;
456 STAMCOUNTER Misc;
457 STAMCOUNTER Bytes;
458 } aStatIsocDetails[8];
459
460 STAMPROFILE StatReapAsyncUrbs;
461 STAMPROFILE StatSubmitUrb;
462 STAMCOUNTER StatFramesProcessedClbk;
463 STAMCOUNTER StatFramesProcessedThread;
464#endif
465} VUSBROOTHUB;
466AssertCompileMemberAlignment(VUSBROOTHUB, IRhConnector, 8);
467AssertCompileMemberAlignment(VUSBROOTHUB, Bitmap, 8);
468AssertCompileMemberAlignment(VUSBROOTHUB, CritSectDevices, 8);
469#ifdef VBOX_WITH_STATISTICS
470AssertCompileMemberAlignment(VUSBROOTHUB, Total, 8);
471#endif
472
473/** Converts a pointer to VUSBROOTHUB::IRhConnector to a PVUSBROOTHUB. */
474#define VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface) (PVUSBROOTHUB)( (uintptr_t)(pInterface) - RT_UOFFSETOF(VUSBROOTHUB, IRhConnector) )
475
476/**
477 * URB cancellation modes
478 */
479typedef enum CANCELMODE
480{
481 /** complete the URB with an error (CRC). */
482 CANCELMODE_FAIL = 0,
483 /** do not change the URB contents. */
484 CANCELMODE_UNDO
485} CANCELMODE;
486
487/** @} */
488
489
490
491/** @defgroup grp_vusb_int_urb Internal URB Operations, Structures and Constants.
492 * @{ */
493int vusbUrbSubmit(PVUSBURB pUrb);
494void vusbUrbDoReapAsync(PRTLISTANCHOR pUrbLst, RTMSINTERVAL cMillies);
495void vusbUrbDoReapAsyncDev(PVUSBDEV pDev, RTMSINTERVAL cMillies);
496void vusbUrbCancel(PVUSBURB pUrb, CANCELMODE mode);
497void vusbUrbCancelAsync(PVUSBURB pUrb, CANCELMODE mode);
498void vusbUrbRipe(PVUSBURB pUrb);
499void vusbUrbCompletionRhEx(PVUSBROOTHUB pRh, PVUSBURB pUrb);
500int vusbUrbSubmitHardError(PVUSBURB pUrb);
501int vusbUrbErrorRhEx(PVUSBROOTHUB pRh, PVUSBURB pUrb);
502int vusbDevUrbIoThreadWakeup(PVUSBDEV pDev);
503int vusbDevUrbIoThreadCreate(PVUSBDEV pDev);
504int vusbDevUrbIoThreadDestroy(PVUSBDEV pDev);
505DECLHIDDEN(void) vusbDevCancelAllUrbs(PVUSBDEV pDev, bool fDetaching);
506DECLHIDDEN(int) vusbDevIoThreadExecV(PVUSBDEV pDev, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args);
507DECLHIDDEN(int) vusbDevIoThreadExec(PVUSBDEV pDev, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
508DECLHIDDEN(int) vusbDevIoThreadExecSync(PVUSBDEV pDev, PFNRT pfnFunction, unsigned cArgs, ...);
509DECLHIDDEN(int) vusbUrbCancelWorker(PVUSBURB pUrb, CANCELMODE enmMode);
510
511DECLHIDDEN(uint64_t) vusbRhR3ProcessFrame(PVUSBROOTHUB pThis, bool fCallback);
512
513int vusbUrbQueueAsyncRh(PVUSBURB pUrb);
514
515bool vusbDevIsDescriptorInCache(PVUSBDEV pDev, PCVUSBSETUP pSetup);
516
517/**
518 * Initializes the given URB pool.
519 *
520 * @returns VBox status code.
521 * @param pUrbPool The URB pool to initialize.
522 */
523DECLHIDDEN(int) vusbUrbPoolInit(PVUSBURBPOOL pUrbPool);
524
525/**
526 * Destroy a given URB pool freeing all ressources.
527 *
528 * @param pUrbPool The URB pool to destroy.
529 */
530DECLHIDDEN(void) vusbUrbPoolDestroy(PVUSBURBPOOL pUrbPool);
531
532/**
533 * Allocate a new URB from the given URB pool.
534 *
535 * @returns Pointer to the new URB or NULL if out of memory.
536 * @param pUrbPool The URB pool to allocate from.
537 * @param enmType Type of the URB.
538 * @param enmDir The direction of the URB.
539 * @param cbData The number of bytes to allocate for the data buffer.
540 * @param cbHci Size of the data private to the HCI for each URB when allocated.
541 * @param cbHciTd Size of one transfer descriptor.
542 * @param cTds Number of transfer descriptors.
543 */
544DECLHIDDEN(PVUSBURB) vusbUrbPoolAlloc(PVUSBURBPOOL pUrbPool, VUSBXFERTYPE enmType,
545 VUSBDIRECTION enmDir, size_t cbData,
546 size_t cbHci, size_t cbHciTd, unsigned cTds);
547
548/**
549 * Frees a given URB.
550 *
551 * @param pUrbPool The URB pool the URB was allocated from.
552 * @param pUrb The URB to free.
553 */
554DECLHIDDEN(void) vusbUrbPoolFree(PVUSBURBPOOL pUrbPool, PVUSBURB pUrb);
555
556#ifdef LOG_ENABLED
557
558/**
559 * Logs an URB in the debug log.
560 *
561 * @param pUrb The URB to log.
562 * @param pszMsg Additional message to log.
563 * @param fComplete Flag whther the URB is completing.
564 */
565DECLHIDDEN(void) vusbUrbTrace(PVUSBURB pUrb, const char *pszMsg, bool fComplete);
566
567/**
568 * Return the USB direction as a string from the given enum.
569 */
570DECLHIDDEN(const char *) vusbUrbDirName(VUSBDIRECTION enmDir);
571
572/**
573 * Return the URB type as string from the given enum.
574 */
575DECLHIDDEN(const char *) vusbUrbTypeName(VUSBXFERTYPE enmType);
576
577/**
578 * Return the URB status as string from the given enum.
579 */
580DECLHIDDEN(const char *) vusbUrbStatusName(VUSBSTATUS enmStatus);
581
582#endif /* LOG_ENABLED*/
583
584DECLINLINE(void) vusbUrbUnlink(PVUSBURB pUrb)
585{
586 PVUSBDEV pDev = pUrb->pVUsb->pDev;
587
588 RTCritSectEnter(&pDev->CritSectAsyncUrbs);
589 RTListNodeRemove(&pUrb->pVUsb->NdLst);
590 RTCritSectLeave(&pDev->CritSectAsyncUrbs);
591}
592
593
594DECLINLINE(int) vusbUrbErrorRh(PVUSBURB pUrb)
595{
596 PVUSBDEV pDev = pUrb->pVUsb->pDev;
597 PVUSBROOTHUB pRh = vusbDevGetRh(pDev);
598 AssertPtrReturn(pRh, VERR_VUSB_DEVICE_NOT_ATTACHED);
599
600 return vusbUrbErrorRhEx(pRh, pUrb);
601}
602
603
604DECLINLINE(void) vusbUrbCompletionRh(PVUSBURB pUrb)
605{
606 PVUSBROOTHUB pRh = vusbDevGetRh(pUrb->pVUsb->pDev);
607 AssertPtrReturnVoid(pRh);
608
609 vusbUrbCompletionRhEx(pRh, pUrb);
610}
611
612
613/** @def vusbUrbAssert
614 * Asserts that a URB is valid.
615 */
616#ifdef VBOX_STRICT
617# define vusbUrbAssert(pUrb) do { \
618 AssertPtr((pUrb)); \
619 AssertMsg((pUrb)->u32Magic == VUSBURB_MAGIC, ("%#x", (pUrb)->u32Magic)); \
620 AssertMsg((pUrb)->enmState > VUSBURBSTATE_INVALID && (pUrb)->enmState < VUSBURBSTATE_END, \
621 ("%d\n", (pUrb)->enmState)); \
622 } while (0)
623#else
624# define vusbUrbAssert(pUrb) do {} while (0)
625#endif
626
627/**
628 * @def VUSBDEV_ASSERT_VALID_STATE
629 * Asserts that the give device state is valid.
630 */
631#define VUSBDEV_ASSERT_VALID_STATE(enmState) \
632 AssertMsg((enmState) > VUSB_DEVICE_STATE_INVALID && (enmState) < VUSB_DEVICE_STATE_DESTROYED, ("enmState=%#x\n", enmState));
633
634/** Executes a function synchronously. */
635#define VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC RT_BIT_32(0)
636
637/** @} */
638
639
640/**
641 * Gets the roothub of a device.
642 *
643 * @returns Pointer to the roothub instance the device is attached to.
644 * @returns NULL if not attached to any hub.
645 * @param pDev Pointer to the device in question.
646 */
647DECLINLINE(PVUSBROOTHUB) vusbDevGetRh(PVUSBDEV pDev)
648{
649 if (!pDev->pHub)
650 return NULL;
651 return pDev->pHub;
652}
653
654
655/**
656 * Returns the state of the USB device.
657 *
658 * @returns State of the USB device.
659 * @param pDev Pointer to the device.
660 */
661DECLINLINE(VUSBDEVICESTATE) vusbDevGetState(PVUSBDEV pDev)
662{
663 VUSBDEVICESTATE enmState = (VUSBDEVICESTATE)ASMAtomicReadU32((volatile uint32_t *)&pDev->enmState);
664 VUSBDEV_ASSERT_VALID_STATE(enmState);
665 return enmState;
666}
667
668
669/**
670 * Sets the given state for the USB device.
671 *
672 * @returns The old state of the device.
673 * @param pDev Pointer to the device.
674 * @param enmState The new state to set.
675 */
676DECLINLINE(VUSBDEVICESTATE) vusbDevSetState(PVUSBDEV pDev, VUSBDEVICESTATE enmState)
677{
678 VUSBDEV_ASSERT_VALID_STATE(enmState);
679 VUSBDEVICESTATE enmStateOld = (VUSBDEVICESTATE)ASMAtomicXchgU32((volatile uint32_t *)&pDev->enmState, enmState);
680 VUSBDEV_ASSERT_VALID_STATE(enmStateOld);
681 return enmStateOld;
682}
683
684
685/**
686 * Compare and exchange the states for the given USB device.
687 *
688 * @returns true if the state was changed.
689 * @returns false if the state wasn't changed.
690 * @param pDev Pointer to the device.
691 * @param enmStateNew The new state to set.
692 * @param enmStateOld The old state to compare with.
693 */
694DECLINLINE(bool) vusbDevSetStateCmp(PVUSBDEV pDev, VUSBDEVICESTATE enmStateNew, VUSBDEVICESTATE enmStateOld)
695{
696 VUSBDEV_ASSERT_VALID_STATE(enmStateNew);
697 VUSBDEV_ASSERT_VALID_STATE(enmStateOld);
698 return ASMAtomicCmpXchgU32((volatile uint32_t *)&pDev->enmState, enmStateNew, enmStateOld);
699}
700
701/**
702 * Retains the given VUSB device pointer.
703 *
704 * @returns New reference count.
705 * @param pThis The VUSB device pointer.
706 * @param pszWho Caller of the retaining.
707 */
708DECLINLINE(uint32_t) vusbDevRetain(PVUSBDEV pThis, const char *pszWho)
709{
710 AssertPtrReturn(pThis, UINT32_MAX);
711
712 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
713 LogFlowFunc(("pThis=%p{.cRefs=%u}[%s]\n", pThis, cRefs, pszWho)); RT_NOREF(pszWho);
714 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
715 return cRefs;
716}
717
718/**
719 * Releases the given VUSB device pointer.
720 *
721 * @returns New reference count.
722 * @retval 0 if no onw is holding a reference anymore causing the device to be destroyed.
723 * @param pThis The VUSB device pointer.
724 * @param pszWho Caller of the retaining.
725 */
726DECLINLINE(uint32_t) vusbDevRelease(PVUSBDEV pThis, const char *pszWho)
727{
728 AssertPtrReturn(pThis, UINT32_MAX);
729
730 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
731 LogFlowFunc(("pThis=%p{.cRefs=%u}[%s]\n", pThis, cRefs, pszWho)); RT_NOREF(pszWho);
732 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
733 if (cRefs == 0)
734 vusbDevDestroy(pThis);
735 return cRefs;
736}
737
738/** Strings for the CTLSTAGE enum values. */
739extern const char * const g_apszCtlStates[4];
740
741/** @} */
742RT_C_DECLS_END
743#endif /* !VBOX_INCLUDED_SRC_USB_VUSBInternal_h */
744
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