VirtualBox

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

Last change on this file since 94377 was 93993, checked in by vboxsync, 3 years ago

Devices/USB: Fix crash introduced with r150219 when a USB device is detached while the roothub tries to queue an URB but can't find the device. Also cancel all in flight URBs after the device was removed from the lookup tables in order to prevent the roothub from queueing URBs simultaneously, bugref:10196

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