VirtualBox

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

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

VUSB: Explicitly ignore any high bits of a USB address which is a 7-bit quantity (see bugref:10433).

  • 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 100517 2023-07-11 14:54:11Z 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
425#if HC_ARCH_BITS == 32
426 uint32_t Alignment1;
427#endif
428
429#ifdef LOG_ENABLED
430 /** A serial number for URBs submitted on the roothub instance.
431 * Only logging builds. */
432 uint32_t iSerial;
433 /** Alignment */
434 uint32_t Alignment2;
435#endif
436#ifdef VBOX_WITH_STATISTICS
437 VUSBROOTHUBTYPESTATS Total;
438 VUSBROOTHUBTYPESTATS aTypes[VUSBXFERTYPE_MSG];
439 STAMCOUNTER StatIsocReqPkts;
440 STAMCOUNTER StatIsocReqReadPkts;
441 STAMCOUNTER StatIsocReqWritePkts;
442 STAMCOUNTER StatIsocActPkts;
443 STAMCOUNTER StatIsocActReadPkts;
444 STAMCOUNTER StatIsocActWritePkts;
445 struct
446 {
447 STAMCOUNTER Pkts;
448 STAMCOUNTER Ok;
449 STAMCOUNTER Ok0;
450 STAMCOUNTER DataUnderrun;
451 STAMCOUNTER DataUnderrun0;
452 STAMCOUNTER DataOverrun;
453 STAMCOUNTER NotAccessed;
454 STAMCOUNTER Misc;
455 STAMCOUNTER Bytes;
456 } aStatIsocDetails[8];
457
458 STAMPROFILE StatReapAsyncUrbs;
459 STAMPROFILE StatSubmitUrb;
460 STAMCOUNTER StatFramesProcessedClbk;
461 STAMCOUNTER StatFramesProcessedThread;
462#endif
463} VUSBROOTHUB;
464AssertCompileMemberAlignment(VUSBROOTHUB, IRhConnector, 8);
465AssertCompileMemberAlignment(VUSBROOTHUB, Bitmap, 8);
466AssertCompileMemberAlignment(VUSBROOTHUB, CritSectDevices, 8);
467#ifdef VBOX_WITH_STATISTICS
468AssertCompileMemberAlignment(VUSBROOTHUB, Total, 8);
469#endif
470
471/** Converts a pointer to VUSBROOTHUB::IRhConnector to a PVUSBROOTHUB. */
472#define VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface) (PVUSBROOTHUB)( (uintptr_t)(pInterface) - RT_UOFFSETOF(VUSBROOTHUB, IRhConnector) )
473
474/**
475 * URB cancellation modes
476 */
477typedef enum CANCELMODE
478{
479 /** complete the URB with an error (CRC). */
480 CANCELMODE_FAIL = 0,
481 /** do not change the URB contents. */
482 CANCELMODE_UNDO
483} CANCELMODE;
484
485/** @} */
486
487
488
489/** @defgroup grp_vusb_int_urb Internal URB Operations, Structures and Constants.
490 * @{ */
491int vusbUrbSubmit(PVUSBURB pUrb);
492void vusbUrbDoReapAsync(PRTLISTANCHOR pUrbLst, RTMSINTERVAL cMillies);
493void vusbUrbDoReapAsyncDev(PVUSBDEV pDev, RTMSINTERVAL cMillies);
494void vusbUrbCancel(PVUSBURB pUrb, CANCELMODE mode);
495void vusbUrbCancelAsync(PVUSBURB pUrb, CANCELMODE mode);
496void vusbUrbRipe(PVUSBURB pUrb);
497void vusbUrbCompletionRhEx(PVUSBROOTHUB pRh, PVUSBURB pUrb);
498int vusbUrbSubmitHardError(PVUSBURB pUrb);
499int vusbUrbErrorRhEx(PVUSBROOTHUB pRh, PVUSBURB pUrb);
500int vusbDevUrbIoThreadWakeup(PVUSBDEV pDev);
501int vusbDevUrbIoThreadCreate(PVUSBDEV pDev);
502int vusbDevUrbIoThreadDestroy(PVUSBDEV pDev);
503DECLHIDDEN(void) vusbDevCancelAllUrbs(PVUSBDEV pDev, bool fDetaching);
504DECLHIDDEN(int) vusbDevIoThreadExecV(PVUSBDEV pDev, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args);
505DECLHIDDEN(int) vusbDevIoThreadExec(PVUSBDEV pDev, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
506DECLHIDDEN(int) vusbDevIoThreadExecSync(PVUSBDEV pDev, PFNRT pfnFunction, unsigned cArgs, ...);
507DECLHIDDEN(int) vusbUrbCancelWorker(PVUSBURB pUrb, CANCELMODE enmMode);
508
509DECLHIDDEN(uint64_t) vusbRhR3ProcessFrame(PVUSBROOTHUB pThis, bool fCallback);
510
511int vusbUrbQueueAsyncRh(PVUSBURB pUrb);
512
513bool vusbDevIsDescriptorInCache(PVUSBDEV pDev, PCVUSBSETUP pSetup);
514
515/**
516 * Initializes the given URB pool.
517 *
518 * @returns VBox status code.
519 * @param pUrbPool The URB pool to initialize.
520 */
521DECLHIDDEN(int) vusbUrbPoolInit(PVUSBURBPOOL pUrbPool);
522
523/**
524 * Destroy a given URB pool freeing all ressources.
525 *
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 * @param pUrbPool The URB pool the URB was allocated from.
550 * @param pUrb The URB to free.
551 */
552DECLHIDDEN(void) vusbUrbPoolFree(PVUSBURBPOOL pUrbPool, PVUSBURB pUrb);
553
554#ifdef LOG_ENABLED
555
556/**
557 * Logs an URB in the debug log.
558 *
559 * @param pUrb The URB to log.
560 * @param pszMsg Additional message to log.
561 * @param fComplete Flag whther the URB is completing.
562 */
563DECLHIDDEN(void) vusbUrbTrace(PVUSBURB pUrb, const char *pszMsg, bool fComplete);
564
565/**
566 * Return the USB direction as a string from the given enum.
567 */
568DECLHIDDEN(const char *) vusbUrbDirName(VUSBDIRECTION enmDir);
569
570/**
571 * Return the URB type as string from the given enum.
572 */
573DECLHIDDEN(const char *) vusbUrbTypeName(VUSBXFERTYPE enmType);
574
575/**
576 * Return the URB status as string from the given enum.
577 */
578DECLHIDDEN(const char *) vusbUrbStatusName(VUSBSTATUS enmStatus);
579
580#endif /* LOG_ENABLED*/
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.

© 2023 Oracle
ContactPrivacy policyTerms of Use