VirtualBox

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

Last change on this file was 106061, checked in by vboxsync, 3 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.5 KB
Line 
1/* $Id: VUSBInternal.h 106061 2024-09-16 14:03:52Z 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-2024 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,
507 unsigned cArgs, va_list Args) RT_IPRT_CALLREQ_ATTR(3, 4, 0);
508DECLHIDDEN(int) vusbDevIoThreadExec(PVUSBDEV pDev, uint32_t fFlags, PFNRT pfnFunction,
509 unsigned cArgs, ...) RT_IPRT_CALLREQ_ATTR(3, 4, 5);
510DECLHIDDEN(int) vusbDevIoThreadExecSync(PVUSBDEV pDev, PFNRT pfnFunction, unsigned cArgs, ...) RT_IPRT_CALLREQ_ATTR(2, 3, 4);
511DECLHIDDEN(int) vusbUrbCancelWorker(PVUSBURB pUrb, CANCELMODE enmMode);
512
513DECLHIDDEN(uint64_t) vusbRhR3ProcessFrame(PVUSBROOTHUB pThis, bool fCallback);
514
515int vusbUrbQueueAsyncRh(PVUSBURB pUrb);
516
517bool vusbDevIsDescriptorInCache(PVUSBDEV pDev, PCVUSBSETUP pSetup);
518
519/**
520 * Initializes the given URB pool.
521 *
522 * @returns VBox status code.
523 * @param pUrbPool The URB pool to initialize.
524 */
525DECLHIDDEN(int) vusbUrbPoolInit(PVUSBURBPOOL pUrbPool);
526
527/**
528 * Destroy a given URB pool freeing all ressources.
529 *
530 * @param pUrbPool The URB pool to destroy.
531 */
532DECLHIDDEN(void) vusbUrbPoolDestroy(PVUSBURBPOOL pUrbPool);
533
534/**
535 * Allocate a new URB from the given URB pool.
536 *
537 * @returns Pointer to the new URB or NULL if out of memory.
538 * @param pUrbPool The URB pool to allocate from.
539 * @param enmType Type of the URB.
540 * @param enmDir The direction of the URB.
541 * @param cbData The number of bytes to allocate for the data buffer.
542 * @param cbHci Size of the data private to the HCI for each URB when allocated.
543 * @param cbHciTd Size of one transfer descriptor.
544 * @param cTds Number of transfer descriptors.
545 */
546DECLHIDDEN(PVUSBURB) vusbUrbPoolAlloc(PVUSBURBPOOL pUrbPool, VUSBXFERTYPE enmType,
547 VUSBDIRECTION enmDir, size_t cbData,
548 size_t cbHci, size_t cbHciTd, unsigned cTds);
549
550/**
551 * Frees a given URB.
552 *
553 * @param pUrbPool The URB pool the URB was allocated from.
554 * @param pUrb The URB to free.
555 */
556DECLHIDDEN(void) vusbUrbPoolFree(PVUSBURBPOOL pUrbPool, PVUSBURB pUrb);
557
558#ifdef LOG_ENABLED
559
560/**
561 * Logs an URB in the debug log.
562 *
563 * @param pUrb The URB to log.
564 * @param pszMsg Additional message to log.
565 * @param fComplete Flag whther the URB is completing.
566 */
567DECLHIDDEN(void) vusbUrbTrace(PVUSBURB pUrb, const char *pszMsg, bool fComplete);
568
569/**
570 * Return the USB direction as a string from the given enum.
571 */
572DECLHIDDEN(const char *) vusbUrbDirName(VUSBDIRECTION enmDir);
573
574/**
575 * Return the URB type as string from the given enum.
576 */
577DECLHIDDEN(const char *) vusbUrbTypeName(VUSBXFERTYPE enmType);
578
579/**
580 * Return the URB status as string from the given enum.
581 */
582DECLHIDDEN(const char *) vusbUrbStatusName(VUSBSTATUS enmStatus);
583
584#endif /* LOG_ENABLED*/
585
586DECLINLINE(void) vusbUrbUnlink(PVUSBURB pUrb)
587{
588 PVUSBDEV pDev = pUrb->pVUsb->pDev;
589
590 RTCritSectEnter(&pDev->CritSectAsyncUrbs);
591 RTListNodeRemove(&pUrb->pVUsb->NdLst);
592 RTCritSectLeave(&pDev->CritSectAsyncUrbs);
593}
594
595
596DECLINLINE(int) vusbUrbErrorRh(PVUSBURB pUrb)
597{
598 PVUSBDEV pDev = pUrb->pVUsb->pDev;
599 PVUSBROOTHUB pRh = vusbDevGetRh(pDev);
600 AssertPtrReturn(pRh, VERR_VUSB_DEVICE_NOT_ATTACHED);
601
602 return vusbUrbErrorRhEx(pRh, pUrb);
603}
604
605
606DECLINLINE(void) vusbUrbCompletionRh(PVUSBURB pUrb)
607{
608 PVUSBROOTHUB pRh = vusbDevGetRh(pUrb->pVUsb->pDev);
609 AssertPtrReturnVoid(pRh);
610
611 vusbUrbCompletionRhEx(pRh, pUrb);
612}
613
614
615/** @def vusbUrbAssert
616 * Asserts that a URB is valid.
617 */
618#ifdef VBOX_STRICT
619# define vusbUrbAssert(pUrb) do { \
620 AssertPtr((pUrb)); \
621 AssertMsg((pUrb)->u32Magic == VUSBURB_MAGIC, ("%#x", (pUrb)->u32Magic)); \
622 AssertMsg((pUrb)->enmState > VUSBURBSTATE_INVALID && (pUrb)->enmState < VUSBURBSTATE_END, \
623 ("%d\n", (pUrb)->enmState)); \
624 } while (0)
625#else
626# define vusbUrbAssert(pUrb) do {} while (0)
627#endif
628
629/**
630 * @def VUSBDEV_ASSERT_VALID_STATE
631 * Asserts that the give device state is valid.
632 */
633#define VUSBDEV_ASSERT_VALID_STATE(enmState) \
634 AssertMsg((enmState) > VUSB_DEVICE_STATE_INVALID && (enmState) < VUSB_DEVICE_STATE_DESTROYED, ("enmState=%#x\n", enmState));
635
636/** Executes a function synchronously. */
637#define VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC RT_BIT_32(0)
638
639/** @} */
640
641
642/**
643 * Gets the roothub of a device.
644 *
645 * @returns Pointer to the roothub instance the device is attached to.
646 * @returns NULL if not attached to any hub.
647 * @param pDev Pointer to the device in question.
648 */
649DECLINLINE(PVUSBROOTHUB) vusbDevGetRh(PVUSBDEV pDev)
650{
651 if (!pDev->pHub)
652 return NULL;
653 return pDev->pHub;
654}
655
656
657/**
658 * Returns the state of the USB device.
659 *
660 * @returns State of the USB device.
661 * @param pDev Pointer to the device.
662 */
663DECLINLINE(VUSBDEVICESTATE) vusbDevGetState(PVUSBDEV pDev)
664{
665 VUSBDEVICESTATE enmState = (VUSBDEVICESTATE)ASMAtomicReadU32((volatile uint32_t *)&pDev->enmState);
666 VUSBDEV_ASSERT_VALID_STATE(enmState);
667 return enmState;
668}
669
670
671/**
672 * Sets the given state for the USB device.
673 *
674 * @returns The old state of the device.
675 * @param pDev Pointer to the device.
676 * @param enmState The new state to set.
677 */
678DECLINLINE(VUSBDEVICESTATE) vusbDevSetState(PVUSBDEV pDev, VUSBDEVICESTATE enmState)
679{
680 VUSBDEV_ASSERT_VALID_STATE(enmState);
681 VUSBDEVICESTATE enmStateOld = (VUSBDEVICESTATE)ASMAtomicXchgU32((volatile uint32_t *)&pDev->enmState, enmState);
682 VUSBDEV_ASSERT_VALID_STATE(enmStateOld);
683 return enmStateOld;
684}
685
686
687/**
688 * Compare and exchange the states for the given USB device.
689 *
690 * @returns true if the state was changed.
691 * @returns false if the state wasn't changed.
692 * @param pDev Pointer to the device.
693 * @param enmStateNew The new state to set.
694 * @param enmStateOld The old state to compare with.
695 */
696DECLINLINE(bool) vusbDevSetStateCmp(PVUSBDEV pDev, VUSBDEVICESTATE enmStateNew, VUSBDEVICESTATE enmStateOld)
697{
698 VUSBDEV_ASSERT_VALID_STATE(enmStateNew);
699 VUSBDEV_ASSERT_VALID_STATE(enmStateOld);
700 return ASMAtomicCmpXchgU32((volatile uint32_t *)&pDev->enmState, enmStateNew, enmStateOld);
701}
702
703/**
704 * Retains the given VUSB device pointer.
705 *
706 * @returns New reference count.
707 * @param pThis The VUSB device pointer.
708 * @param pszWho Caller of the retaining.
709 */
710DECLINLINE(uint32_t) vusbDevRetain(PVUSBDEV pThis, const char *pszWho)
711{
712 AssertPtrReturn(pThis, UINT32_MAX);
713
714 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
715 LogFlowFunc(("pThis=%p{.cRefs=%u}[%s]\n", pThis, cRefs, pszWho)); RT_NOREF(pszWho);
716 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
717 return cRefs;
718}
719
720/**
721 * Releases the given VUSB device pointer.
722 *
723 * @returns New reference count.
724 * @retval 0 if no onw is holding a reference anymore causing the device to be destroyed.
725 * @param pThis The VUSB device pointer.
726 * @param pszWho Caller of the retaining.
727 */
728DECLINLINE(uint32_t) vusbDevRelease(PVUSBDEV pThis, const char *pszWho)
729{
730 AssertPtrReturn(pThis, UINT32_MAX);
731
732 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
733 LogFlowFunc(("pThis=%p{.cRefs=%u}[%s]\n", pThis, cRefs, pszWho)); RT_NOREF(pszWho);
734 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
735 if (cRefs == 0)
736 vusbDevDestroy(pThis);
737 return cRefs;
738}
739
740/** Strings for the CTLSTAGE enum values. */
741extern const char * const g_apszCtlStates[4];
742
743/** @} */
744RT_C_DECLS_END
745#endif /* !VBOX_INCLUDED_SRC_USB_VUSBInternal_h */
746
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