VirtualBox

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

Last change on this file since 62148 was 59875, checked in by vboxsync, 9 years ago

VUSB: Move the thread for periodic frame procession down to the roothub. There we don't need to replicate the code to EHCI later and it has much better overview of the amount of active URBs to schedule when to process new frames

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