VirtualBox

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

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