VirtualBox

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

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

Devices/USB: Convert the HCI emulations to call into the roothub using the devices port instead of using the VUSBIDEVICE interface directly. This will avoid races when devices will get detached unexpectedly while being in use. Also move the device re-attach logic after a saved state operation down to the roothub in order to avoid code duplication, bugref:10196

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.4 KB
Line 
1/* $Id: VUSBInternal.h 93914 2022-02-24 12:20:43Z 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.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 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 /** Next device in the chain maintained by the roothub. */
228 PVUSBDEV pNext;
229 /** Pointer to the next device with the same address hash. */
230 PVUSBDEV pNextHash;
231 /** Pointer to the hub this device is attached to. */
232 PVUSBHUB pHub;
233 /** The device state. */
234 VUSBDEVICESTATE volatile enmState;
235 /** Reference counter to protect the device structure from going away. */
236 uint32_t volatile cRefs;
237
238 /** The device address. */
239 uint8_t u8Address;
240 /** The new device address. */
241 uint8_t u8NewAddress;
242 /** The port. */
243 int16_t i16Port;
244 /** Device status. (VUSB_DEV_SELF_POWERED or not.) */
245 uint16_t u16Status;
246
247 /** Pointer to the descriptor cache.
248 * (Provided by the device thru the pfnGetDescriptorCache method.) */
249 PCPDMUSBDESCCACHE pDescCache;
250 /** Current configuration. */
251 PCVUSBDESCCONFIGEX pCurCfgDesc;
252
253 /** Current interface state (including alternate interface setting) - maximum
254 * valid index is config->bNumInterfaces
255 */
256 PVUSBINTERFACESTATE paIfStates;
257
258 /** Pipe/direction -> endpoint descriptor mapping */
259 VUSBPIPE aPipes[VUSB_PIPE_MAX];
260 /** Critical section protecting the active URB list. */
261 RTCRITSECT CritSectAsyncUrbs;
262 /** List of active async URBs. */
263 RTLISTANCHOR LstAsyncUrbs;
264
265 /** Dumper state. */
266 union VUSBDEVURBDUMPERSTATE
267 {
268 /** The current scsi command. */
269 uint8_t u8ScsiCmd;
270 } Urb;
271
272 /** The reset timer handle. */
273 TMTIMERHANDLE hResetTimer;
274 /** Reset handler arguments. */
275 void *pvArgs;
276 /** URB submit and reap thread. */
277 RTTHREAD hUrbIoThread;
278 /** Request queue for executing tasks on the I/O thread which should be done
279 * synchronous and without any other thread accessing the USB device. */
280 RTREQQUEUE hReqQueueSync;
281 /** Sniffer instance for this device if configured. */
282 VUSBSNIFFER hSniffer;
283 /** Flag whether the URB I/O thread should terminate. */
284 bool volatile fTerminate;
285 /** Flag whether the I/O thread was woken up. */
286 bool volatile fWokenUp;
287#if HC_ARCH_BITS == 32
288 /** Align the size to a 8 byte boundary. */
289 bool afAlignment0[2];
290#endif
291 /** The pool of free URBs for faster allocation. */
292 VUSBURBPOOL UrbPool;
293} VUSBDEV;
294AssertCompileSizeAlignment(VUSBDEV, 8);
295
296
297int vusbDevInit(PVUSBDEV pDev, PPDMUSBINS pUsbIns, const char *pszCaptureFilename);
298void vusbDevDestroy(PVUSBDEV pDev);
299
300DECLINLINE(bool) vusbDevIsRh(PVUSBDEV pDev)
301{
302 return (pDev->pHub == (PVUSBHUB)pDev);
303}
304
305bool vusbDevDoSelectConfig(PVUSBDEV dev, PCVUSBDESCCONFIGEX pCfg);
306void vusbDevMapEndpoint(PVUSBDEV dev, PCVUSBDESCENDPOINTEX ep);
307int vusbDevDetach(PVUSBDEV pDev);
308int vusbDevAttach(PVUSBDEV pDev, PVUSBHUB pHub);
309DECLINLINE(PVUSBROOTHUB) vusbDevGetRh(PVUSBDEV pDev);
310size_t vusbDevMaxInterfaces(PVUSBDEV dev);
311
312void vusbDevSetAddress(PVUSBDEV pDev, uint8_t u8Address);
313bool vusbDevStandardRequest(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, void *pvBuf, uint32_t *pcbBuf);
314
315
316/** @} */
317
318
319/** @defgroup grp_vusb_int_hub Internal Hub Operations, Structures and Constants.
320 * @{
321 */
322
323
324/** Virtual method table for USB hub devices.
325 * Hub and roothub drivers need to implement these functions in addition to the
326 * vusb_dev_ops.
327 */
328typedef struct VUSBHUBOPS
329{
330 int (*pfnAttach)(PVUSBHUB pHub, PVUSBDEV pDev);
331 void (*pfnDetach)(PVUSBHUB pHub, PVUSBDEV pDev);
332} VUSBHUBOPS;
333/** Pointer to a const HUB method table. */
334typedef const VUSBHUBOPS *PCVUSBHUBOPS;
335
336/** A VUSB Hub Device - Hub and roothub drivers need to use this struct
337 * @todo eliminate this (PDM / roothubs only).
338 */
339typedef struct VUSBHUB
340{
341 VUSBDEV Dev;
342 PCVUSBHUBOPS pOps;
343 PVUSBROOTHUB pRootHub;
344 uint16_t cPorts;
345 uint16_t cDevices;
346 /** Name of the hub. Used for logging. */
347 char *pszName;
348} VUSBHUB;
349AssertCompileMemberAlignment(VUSBHUB, pOps, 8);
350AssertCompileSizeAlignment(VUSBHUB, 8);
351
352/** @} */
353
354
355/** @defgroup grp_vusb_int_roothub Internal Root Hub Operations, Structures and Constants.
356 * @{
357 */
358
359/**
360 * Per transfer type statistics.
361 */
362typedef struct VUSBROOTHUBTYPESTATS
363{
364 STAMCOUNTER StatUrbsSubmitted;
365 STAMCOUNTER StatUrbsFailed;
366 STAMCOUNTER StatUrbsCancelled;
367
368 STAMCOUNTER StatReqBytes;
369 STAMCOUNTER StatReqReadBytes;
370 STAMCOUNTER StatReqWriteBytes;
371
372 STAMCOUNTER StatActBytes;
373 STAMCOUNTER StatActReadBytes;
374 STAMCOUNTER StatActWriteBytes;
375} VUSBROOTHUBTYPESTATS, *PVUSBROOTHUBTYPESTATS;
376
377
378
379/** Pointer to a VUSBROOTHUBLOAD struct. */
380typedef struct VUSBROOTHUBLOAD *PVUSBROOTHUBLOAD;
381
382/** The address hash table size. */
383#define VUSB_ADDR_HASHSZ 5
384
385/**
386 * The instance data of a root hub driver.
387 *
388 * This extends the generic VUSB hub.
389 *
390 * @implements VUSBIROOTHUBCONNECTOR
391 */
392typedef struct VUSBROOTHUB
393{
394 /** The HUB.
395 * @todo remove this? */
396 VUSBHUB Hub;
397 /** Address hash table. */
398 PVUSBDEV apAddrHash[VUSB_ADDR_HASHSZ];
399 /** The default address. */
400 PVUSBDEV pDefaultAddress;
401
402 /** Pointer to the driver instance. */
403 PPDMDRVINS pDrvIns;
404 /** Pointer to the root hub port interface we're attached to. */
405 PVUSBIROOTHUBPORT pIRhPort;
406 /** Connector interface exposed upwards. */
407 VUSBIROOTHUBCONNECTOR IRhConnector;
408
409 /** Critical section protecting the device list. */
410 RTCRITSECT CritSectDevices;
411 /** Chain of devices attached to this hub. */
412 PVUSBDEV pDevices;
413
414 /** Array of pointers to USB devices indexed by the port the device is on. */
415 PVUSBDEV apDevByPort[VUSB_DEVICES_MAX];
416 /** Structure after a saved state load to re-attach devices. */
417 PVUSBROOTHUBLOAD pLoad;
418
419#if HC_ARCH_BITS == 32
420 uint32_t Alignment0;
421#endif
422
423 /** Availability Bitmap. */
424 VUSBPORTBITMAP Bitmap;
425
426 /** Sniffer instance for the root hub. */
427 VUSBSNIFFER hSniffer;
428 /** Version of the attached Host Controller. */
429 uint32_t fHcVersions;
430 /** Size of the HCI specific data for each URB. */
431 size_t cbHci;
432 /** Size of the HCI specific TD. */
433 size_t cbHciTd;
434
435 /** The periodic frame processing thread. */
436 R3PTRTYPE(PPDMTHREAD) hThreadPeriodFrame;
437 /** Event semaphore to interact with the periodic frame processing thread. */
438 R3PTRTYPE(RTSEMEVENTMULTI) hSemEventPeriodFrame;
439 /** Event semaphore to release the thread waiting for the periodic frame processing thread to stop. */
440 R3PTRTYPE(RTSEMEVENTMULTI) hSemEventPeriodFrameStopped;
441 /** Current default frame rate for periodic frame processing thread. */
442 volatile uint32_t uFrameRateDefault;
443 /** Current frame rate (can be lower than the default frame rate if there is no activity). */
444 uint32_t uFrameRate;
445 /** How long to wait until the next frame. */
446 uint64_t nsWait;
447 /** Timestamp when the last frame was processed. */
448 uint64_t tsFrameProcessed;
449 /** Number of USB work cycles with no transfers. */
450 uint32_t cIdleCycles;
451
452 /** Flag whether a frame is currently being processed. */
453 volatile bool fFrameProcessing;
454
455#if HC_ARCH_BITS == 32
456 uint32_t Alignment1;
457#endif
458
459#ifdef LOG_ENABLED
460 /** A serial number for URBs submitted on the roothub instance.
461 * Only logging builds. */
462 uint32_t iSerial;
463 /** Alignment */
464 uint32_t Alignment2;
465#endif
466#ifdef VBOX_WITH_STATISTICS
467 VUSBROOTHUBTYPESTATS Total;
468 VUSBROOTHUBTYPESTATS aTypes[VUSBXFERTYPE_MSG];
469 STAMCOUNTER StatIsocReqPkts;
470 STAMCOUNTER StatIsocReqReadPkts;
471 STAMCOUNTER StatIsocReqWritePkts;
472 STAMCOUNTER StatIsocActPkts;
473 STAMCOUNTER StatIsocActReadPkts;
474 STAMCOUNTER StatIsocActWritePkts;
475 struct
476 {
477 STAMCOUNTER Pkts;
478 STAMCOUNTER Ok;
479 STAMCOUNTER Ok0;
480 STAMCOUNTER DataUnderrun;
481 STAMCOUNTER DataUnderrun0;
482 STAMCOUNTER DataOverrun;
483 STAMCOUNTER NotAccessed;
484 STAMCOUNTER Misc;
485 STAMCOUNTER Bytes;
486 } aStatIsocDetails[8];
487
488 STAMPROFILE StatReapAsyncUrbs;
489 STAMPROFILE StatSubmitUrb;
490 STAMCOUNTER StatFramesProcessedClbk;
491 STAMCOUNTER StatFramesProcessedThread;
492#endif
493} VUSBROOTHUB;
494AssertCompileMemberAlignment(VUSBROOTHUB, IRhConnector, 8);
495AssertCompileMemberAlignment(VUSBROOTHUB, Bitmap, 8);
496AssertCompileMemberAlignment(VUSBROOTHUB, CritSectDevices, 8);
497#ifdef VBOX_WITH_STATISTICS
498AssertCompileMemberAlignment(VUSBROOTHUB, Total, 8);
499#endif
500
501/** Converts a pointer to VUSBROOTHUB::IRhConnector to a PVUSBROOTHUB. */
502#define VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface) (PVUSBROOTHUB)( (uintptr_t)(pInterface) - RT_UOFFSETOF(VUSBROOTHUB, IRhConnector) )
503
504/**
505 * URB cancellation modes
506 */
507typedef enum CANCELMODE
508{
509 /** complete the URB with an error (CRC). */
510 CANCELMODE_FAIL = 0,
511 /** do not change the URB contents. */
512 CANCELMODE_UNDO
513} CANCELMODE;
514
515/** @} */
516
517
518
519/** @defgroup grp_vusb_int_urb Internal URB Operations, Structures and Constants.
520 * @{ */
521int vusbUrbSubmit(PVUSBURB pUrb);
522void vusbUrbDoReapAsync(PRTLISTANCHOR pUrbLst, RTMSINTERVAL cMillies);
523void vusbUrbDoReapAsyncDev(PVUSBDEV pDev, RTMSINTERVAL cMillies);
524void vusbUrbCancel(PVUSBURB pUrb, CANCELMODE mode);
525void vusbUrbCancelAsync(PVUSBURB pUrb, CANCELMODE mode);
526void vusbUrbRipe(PVUSBURB pUrb);
527void vusbUrbCompletionRh(PVUSBURB pUrb);
528int vusbUrbSubmitHardError(PVUSBURB pUrb);
529int vusbUrbErrorRh(PVUSBURB pUrb);
530int vusbDevUrbIoThreadWakeup(PVUSBDEV pDev);
531int vusbDevUrbIoThreadCreate(PVUSBDEV pDev);
532int vusbDevUrbIoThreadDestroy(PVUSBDEV pDev);
533DECLHIDDEN(void) vusbDevCancelAllUrbs(PVUSBDEV pDev, bool fDetaching);
534DECLHIDDEN(int) vusbDevIoThreadExecV(PVUSBDEV pDev, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args);
535DECLHIDDEN(int) vusbDevIoThreadExec(PVUSBDEV pDev, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
536DECLHIDDEN(int) vusbDevIoThreadExecSync(PVUSBDEV pDev, PFNRT pfnFunction, unsigned cArgs, ...);
537DECLHIDDEN(int) vusbUrbCancelWorker(PVUSBURB pUrb, CANCELMODE enmMode);
538
539DECLHIDDEN(uint64_t) vusbRhR3ProcessFrame(PVUSBROOTHUB pThis, bool fCallback);
540
541int vusbUrbQueueAsyncRh(PVUSBURB pUrb);
542
543bool vusbDevIsDescriptorInCache(PVUSBDEV pDev, PCVUSBSETUP pSetup);
544
545/**
546 * Initializes the given URB pool.
547 *
548 * @returns VBox status code.
549 * @param pUrbPool The URB pool to initialize.
550 */
551DECLHIDDEN(int) vusbUrbPoolInit(PVUSBURBPOOL pUrbPool);
552
553/**
554 * Destroy a given URB pool freeing all ressources.
555 *
556 * @returns nothing.
557 * @param pUrbPool The URB pool to destroy.
558 */
559DECLHIDDEN(void) vusbUrbPoolDestroy(PVUSBURBPOOL pUrbPool);
560
561/**
562 * Allocate a new URB from the given URB pool.
563 *
564 * @returns Pointer to the new URB or NULL if out of memory.
565 * @param pUrbPool The URB pool to allocate from.
566 * @param enmType Type of the URB.
567 * @param enmDir The direction of the URB.
568 * @param cbData The number of bytes to allocate for the data buffer.
569 * @param cbHci Size of the data private to the HCI for each URB when allocated.
570 * @param cbHciTd Size of one transfer descriptor.
571 * @param cTds Number of transfer descriptors.
572 */
573DECLHIDDEN(PVUSBURB) vusbUrbPoolAlloc(PVUSBURBPOOL pUrbPool, VUSBXFERTYPE enmType,
574 VUSBDIRECTION enmDir, size_t cbData,
575 size_t cbHci, size_t cbHciTd, unsigned cTds);
576
577/**
578 * Frees a given URB.
579 *
580 * @returns nothing.
581 * @param pUrbPool The URB pool the URB was allocated from.
582 * @param pUrb The URB to free.
583 */
584DECLHIDDEN(void) vusbUrbPoolFree(PVUSBURBPOOL pUrbPool, PVUSBURB pUrb);
585
586#ifdef LOG_ENABLED
587/**
588 * Logs an URB in the debug log.
589 *
590 * @returns nothing.
591 * @param pUrb The URB to log.
592 * @param pszMsg Additional message to log.
593 * @param fComplete Flag whther the URB is completing.
594 */
595DECLHIDDEN(void) vusbUrbTrace(PVUSBURB pUrb, const char *pszMsg, bool fComplete);
596
597/**
598 * Return the USB direction as a string from the given enum.
599 */
600DECLHIDDEN(const char *) vusbUrbDirName(VUSBDIRECTION enmDir);
601
602/**
603 * Return the URB type as string from the given enum.
604 */
605DECLHIDDEN(const char *) vusbUrbTypeName(VUSBXFERTYPE enmType);
606
607/**
608 * Return the URB status as string from the given enum.
609 */
610DECLHIDDEN(const char *) vusbUrbStatusName(VUSBSTATUS enmStatus);
611#endif
612
613DECLINLINE(void) vusbUrbUnlink(PVUSBURB pUrb)
614{
615 PVUSBDEV pDev = pUrb->pVUsb->pDev;
616
617 RTCritSectEnter(&pDev->CritSectAsyncUrbs);
618 RTListNodeRemove(&pUrb->pVUsb->NdLst);
619 RTCritSectLeave(&pDev->CritSectAsyncUrbs);
620}
621
622/** @def vusbUrbAssert
623 * Asserts that a URB is valid.
624 */
625#ifdef VBOX_STRICT
626# define vusbUrbAssert(pUrb) do { \
627 AssertPtr((pUrb)); \
628 AssertMsg((pUrb)->u32Magic == VUSBURB_MAGIC, ("%#x", (pUrb)->u32Magic)); \
629 AssertMsg((pUrb)->enmState > VUSBURBSTATE_INVALID && (pUrb)->enmState < VUSBURBSTATE_END, \
630 ("%d\n", (pUrb)->enmState)); \
631 } while (0)
632#else
633# define vusbUrbAssert(pUrb) do {} while (0)
634#endif
635
636/**
637 * @def VUSBDEV_ASSERT_VALID_STATE
638 * Asserts that the give device state is valid.
639 */
640#define VUSBDEV_ASSERT_VALID_STATE(enmState) \
641 AssertMsg((enmState) > VUSB_DEVICE_STATE_INVALID && (enmState) < VUSB_DEVICE_STATE_DESTROYED, ("enmState=%#x\n", enmState));
642
643/** Executes a function synchronously. */
644#define VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC RT_BIT_32(0)
645
646/** @} */
647
648
649
650
651/**
652 * Addresses are between 0 and 127 inclusive
653 */
654DECLINLINE(uint8_t) vusbHashAddress(uint8_t Address)
655{
656 uint8_t u8Hash = Address;
657 u8Hash ^= (Address >> 2);
658 u8Hash ^= (Address >> 3);
659 u8Hash %= VUSB_ADDR_HASHSZ;
660 return u8Hash;
661}
662
663
664/**
665 * Gets the roothub of a device.
666 *
667 * @returns Pointer to the roothub instance the device is attached to.
668 * @returns NULL if not attached to any hub.
669 * @param pDev Pointer to the device in question.
670 */
671DECLINLINE(PVUSBROOTHUB) vusbDevGetRh(PVUSBDEV pDev)
672{
673 if (!pDev->pHub)
674 return NULL;
675 return pDev->pHub->pRootHub;
676}
677
678
679/**
680 * Returns the state of the USB device.
681 *
682 * @returns State of the USB device.
683 * @param pDev Pointer to the device.
684 */
685DECLINLINE(VUSBDEVICESTATE) vusbDevGetState(PVUSBDEV pDev)
686{
687 VUSBDEVICESTATE enmState = (VUSBDEVICESTATE)ASMAtomicReadU32((volatile uint32_t *)&pDev->enmState);
688 VUSBDEV_ASSERT_VALID_STATE(enmState);
689 return enmState;
690}
691
692
693/**
694 * Sets the given state for the USB device.
695 *
696 * @returns The old state of the device.
697 * @param pDev Pointer to the device.
698 * @param enmState The new state to set.
699 */
700DECLINLINE(VUSBDEVICESTATE) vusbDevSetState(PVUSBDEV pDev, VUSBDEVICESTATE enmState)
701{
702 VUSBDEV_ASSERT_VALID_STATE(enmState);
703 VUSBDEVICESTATE enmStateOld = (VUSBDEVICESTATE)ASMAtomicXchgU32((volatile uint32_t *)&pDev->enmState, enmState);
704 VUSBDEV_ASSERT_VALID_STATE(enmStateOld);
705 return enmStateOld;
706}
707
708
709/**
710 * Compare and exchange the states for the given USB device.
711 *
712 * @returns true if the state was changed.
713 * @returns false if the state wasn't changed.
714 * @param pDev Pointer to the device.
715 * @param enmStateNew The new state to set.
716 * @param enmStateOld The old state to compare with.
717 */
718DECLINLINE(bool) vusbDevSetStateCmp(PVUSBDEV pDev, VUSBDEVICESTATE enmStateNew, VUSBDEVICESTATE enmStateOld)
719{
720 VUSBDEV_ASSERT_VALID_STATE(enmStateNew);
721 VUSBDEV_ASSERT_VALID_STATE(enmStateOld);
722 return ASMAtomicCmpXchgU32((volatile uint32_t *)&pDev->enmState, enmStateNew, enmStateOld);
723}
724
725/**
726 * Retains the given VUSB device pointer.
727 *
728 * @returns New reference count.
729 * @param pThis The VUSB device pointer.
730 */
731DECLINLINE(uint32_t) vusbDevRetain(PVUSBDEV pThis)
732{
733 AssertPtrReturn(pThis, UINT32_MAX);
734
735 uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
736 AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
737 return cRefs;
738}
739
740/**
741 * Releases the given VUSB device pointer.
742 *
743 * @returns New reference count.
744 * @retval 0 if no onw is holding a reference anymore causing the device to be destroyed.
745 */
746DECLINLINE(uint32_t) vusbDevRelease(PVUSBDEV pThis)
747{
748 AssertPtrReturn(pThis, UINT32_MAX);
749
750 uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
751 AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
752 if (cRefs == 0)
753 vusbDevDestroy(pThis);
754 return cRefs;
755}
756
757/** Strings for the CTLSTAGE enum values. */
758extern const char * const g_apszCtlStates[4];
759
760/** @} */
761RT_C_DECLS_END
762#endif /* !VBOX_INCLUDED_SRC_USB_VUSBInternal_h */
763
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