VirtualBox

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

最後變更 在這個檔案從93974是 93974,由 vboxsync 提交於 3 年 前

Devices/USB: Fix for regression introduced with r150168 where a guest failed to enumerate USB devices if more than one device was on the bus when the VM was powered on. Simplify the code even more to not require any lists for devices in the default state, bugref:10196

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette