VirtualBox

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

Last change on this file since 27867 was 26970, checked in by vboxsync, 15 years ago

Export code for handling virtual USB devices to OSE, mainly for emulating USB mouse and USB keyboard. This does NOT include support for passing through USB host devices!

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.6 KB
Line 
1/* $Id: VUSBInternal.h 26970 2010-03-02 20:43:37Z 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-2007 Sun Microsystems, Inc.
13 *
14 * Sun Microsystems, Inc. confidential
15 * All rights reserved
16 */
17
18#ifndef ___VUSBInternal_h
19#define ___VUSBInternal_h
20
21#include <VBox/cdefs.h>
22#include <VBox/types.h>
23#include <VBox/vusb.h>
24#include <VBox/stam.h>
25
26RT_C_DECLS_BEGIN
27
28
29/** @name Internal Device Operations, Structures and Constants.
30 * @{
31 */
32
33/** Pointer to a Virtual USB device (core). */
34typedef struct VUSBDEV *PVUSBDEV;
35/** Pointer to a VUSB hub device. */
36typedef struct VUSBHUB *PVUSBHUB;
37/** Pointer to a VUSB root hub. */
38typedef struct VUSBROOTHUB *PVUSBROOTHUB;
39
40
41/** Number of the default control endpoint */
42#define VUSB_PIPE_DEFAULT 0
43
44/** @name Device addresses
45 * @{ */
46#define VUSB_DEFAULT_ADDRESS 0
47#define VUSB_INVALID_ADDRESS UINT8_C(0xff)
48/** @} */
49
50/** @name Feature bits (1<<FEATURE for the u16Status bit)
51 * @{ */
52#define VUSB_DEV_SELF_POWERED 0
53#define VUSB_DEV_REMOTE_WAKEUP 1
54#define VUSB_EP_HALT 0
55/** @} */
56
57/** Maximum number of endpoint addresses */
58#define VUSB_PIPE_MAX 16
59
60/**
61 * Control-pipe stages.
62 */
63typedef enum CTLSTAGE
64{
65 /** the control pipe is in the setup stage. */
66 CTLSTAGE_SETUP = 0,
67 /** the control pipe is in the data stage. */
68 CTLSTAGE_DATA,
69 /** the control pipe is in the status stage. */
70 CTLSTAGE_STATUS
71} CTLSTAGE;
72
73/**
74 * Extra data for a control pipe.
75 *
76 * This is state information needed for the special multi-stage
77 * transfers performed on this kind of pipes.
78 */
79typedef struct vusb_ctrl_extra
80{
81 /** Current pipe stage. */
82 CTLSTAGE enmStage;
83 /** Success indicator. */
84 bool fOk;
85 /** Set if the message URB has been submitted. */
86 bool fSubmitted;
87 /** Pointer to the SETUP.
88 * This is a pointer to Urb->abData[0]. */
89 PVUSBSETUP pMsg;
90 /** Current DATA pointer.
91 * This starts at pMsg + 1 and is incremented at we read/write data. */
92 uint8_t *pbCur;
93 /** The amount of data left to read on IN operations.
94 * On OUT operations this is not used. */
95 uint32_t cbLeft;
96 /** The amount of data we can house.
97 * This starts at the default 8KB, and this structure will be reallocated to
98 * accommodate any larger request (unlikely). */
99 uint32_t cbMax;
100 /** The message URB. */
101 VUSBURB Urb;
102} VUSBCTRLEXTRA, *PVUSBCTRLEXTRA;
103
104void vusbMsgFreeExtraData(PVUSBCTRLEXTRA pExtra);
105void vusbMsgResetExtraData(PVUSBCTRLEXTRA pExtra);
106
107
108/**
109 * A VUSB pipe
110 */
111typedef struct vusb_pipe
112{
113 PCVUSBDESCENDPOINTEX in;
114 PCVUSBDESCENDPOINTEX out;
115 /** Pointer to the extra state data required to run a control pipe. */
116 PVUSBCTRLEXTRA pCtrl;
117 /** Count of active async transfers. */
118 uint8_t async;
119 /** The periodic read-ahead buffer thread. */
120 RTTHREAD ReadAheadThread;
121 /** Pointer to the reset thread arguments. */
122 void *pvReadAheadArgs;
123 /** Pointer to the first buffered URB. */
124 PVUSBURB pBuffUrbHead;
125 /** Pointer to the last buffered URB. */
126 PVUSBURB pBuffUrbTail;
127 /** Count of URBs in read-ahead buffer. */
128 uint32_t cBuffered;
129 /** Count of URBs submitted for read-ahead but not yet reaped. */
130 uint32_t cSubmitted;
131} VUSBPIPE;
132/** Pointer to a VUSB pipe structure. */
133typedef VUSBPIPE *PVUSBPIPE;
134
135
136/**
137 * Interface state and possible settings.
138 */
139typedef struct vusb_interface_state
140{
141 /** Pointer to the interface descriptor of the currently selected (active)
142 * interface. */
143 PCVUSBDESCINTERFACEEX pCurIfDesc;
144 /** Pointer to the interface settings. */
145 PCVUSBINTERFACE pIf;
146} VUSBINTERFACESTATE;
147/** Pointer to interface state. */
148typedef VUSBINTERFACESTATE *PVUSBINTERFACESTATE;
149/** Pointer to const interface state. */
150typedef const VUSBINTERFACESTATE *PCVUSBINTERFACESTATE;
151
152
153/**
154 * A Virtual USB device (core).
155 *
156 * @implements VUSBIDEVICE
157 */
158typedef struct VUSBDEV
159{
160 /** The device interface exposed to the HCI. */
161 VUSBIDEVICE IDevice;
162 /** Pointer to the PDM USB device instance. */
163 PPDMUSBINS pUsbIns;
164 /** Next device in the chain maintained by the roothub. */
165 PVUSBDEV pNext;
166 /** Pointer to the next device with the same address hash. */
167 PVUSBDEV pNextHash;
168 /** Pointer to the hub this device is attached to. */
169 PVUSBHUB pHub;
170 /** The device state.
171 * Only EMT changes this value. */
172 VUSBDEVICESTATE volatile enmState;
173
174 /** The device address. */
175 uint8_t u8Address;
176 /** The new device address. */
177 uint8_t u8NewAddress;
178 /** The port. */
179 int16_t i16Port;
180 /** Device status. (VUSB_DEV_SELF_POWERED or not.) */
181 uint16_t u16Status;
182
183 /** Pointer to the descriptor cache.
184 * (Provided by the device thru the pfnGetDescriptorCache method.) */
185 PCPDMUSBDESCCACHE pDescCache;
186 /** Current configuration. */
187 PCVUSBDESCCONFIGEX pCurCfgDesc;
188
189 /** Current interface state (including alternate interface setting) - maximum
190 * valid index is config->bNumInterfaces
191 */
192 PVUSBINTERFACESTATE paIfStates;
193
194 /** Pipe/direction -> endpoint descriptor mapping */
195 VUSBPIPE aPipes[VUSB_PIPE_MAX];
196
197 /** Dumper state. */
198 union VUSBDEVURBDUMPERSTATE
199 {
200 /** The current scsi command. */
201 uint8_t u8ScsiCmd;
202 } Urb;
203
204 /** The reset thread. */
205 RTTHREAD hResetThread;
206 /** Pointer to the reset thread arguments. */
207 void *pvResetArgs;
208} VUSBDEV;
209
210
211
212/** Pointer to the virtual method table for a kind of USB devices. */
213typedef struct vusb_dev_ops *PVUSBDEVOPS;
214
215/** Pointer to the const virtual method table for a kind of USB devices. */
216typedef const struct vusb_dev_ops *PCVUSBDEVOPS;
217
218/**
219 * Virtual method table for USB devices - these are the functions you need to
220 * implement when writing a new device (or hub)
221 *
222 * Note that when creating your structure, you are required to zero the
223 * vusb_dev fields (ie. use calloc).
224 */
225typedef struct vusb_dev_ops
226{
227 /* mandatory */
228 const char *name;
229} VUSBDEVOPS;
230
231
232int vusbDevInit(PVUSBDEV pDev, PPDMUSBINS pUsbIns);
233int vusbDevCreateOld(const char *pszDeviceName, void *pvDriverInit, PCRTUUID pUuid, PVUSBDEV *ppDev);
234void vusbDevDestroy(PVUSBDEV pDev);
235
236DECLINLINE(bool) vusbDevIsRh(PVUSBDEV pDev)
237{
238 return (pDev->pHub == (PVUSBHUB)pDev);
239}
240
241bool vusbDevDoSelectConfig(PVUSBDEV dev, PCVUSBDESCCONFIGEX pCfg);
242void vusbDevMapEndpoint(PVUSBDEV dev, PCVUSBDESCENDPOINTEX ep);
243int vusbDevDetach(PVUSBDEV pDev);
244DECLINLINE(PVUSBROOTHUB) vusbDevGetRh(PVUSBDEV pDev);
245size_t vusbDevMaxInterfaces(PVUSBDEV dev);
246
247DECLCALLBACK(int) vusbDevReset(PVUSBIDEVICE pDevice, bool fResetOnLinux, PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM);
248DECLCALLBACK(int) vusbDevPowerOn(PVUSBIDEVICE pInterface);
249DECLCALLBACK(int) vusbDevPowerOff(PVUSBIDEVICE pInterface);
250DECLCALLBACK(VUSBDEVICESTATE) vusbDevGetState(PVUSBIDEVICE pInterface);
251void vusbDevSetAddress(PVUSBDEV pDev, uint8_t u8Address);
252bool vusbDevStandardRequest(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, void *pvBuf, uint32_t *pcbBuf);
253
254
255/** @} */
256
257
258
259
260
261/** @name Internal Hub Operations, Structures and Constants.
262 * @{
263 */
264
265
266/** Virtual method table for USB hub devices.
267 * Hub and roothub drivers need to implement these functions in addition to the
268 * vusb_dev_ops.
269 */
270typedef struct VUSBHUBOPS
271{
272 int (*pfnAttach)(PVUSBHUB pHub, PVUSBDEV pDev);
273 void (*pfnDetach)(PVUSBHUB pHub, PVUSBDEV pDev);
274} VUSBHUBOPS;
275/** Pointer to a const HUB method table. */
276typedef const VUSBHUBOPS *PCVUSBHUBOPS;
277
278/** A VUSB Hub Device - Hub and roothub drivers need to use this struct
279 * @todo eliminate this (PDM / roothubs only).
280 */
281typedef struct VUSBHUB
282{
283 VUSBDEV Dev;
284 PCVUSBHUBOPS pOps;
285 PVUSBROOTHUB pRootHub;
286 uint16_t cPorts;
287 uint16_t cDevices;
288 /** Name of the hub. Used for logging. */
289 char *pszName;
290} VUSBHUB;
291
292/** @} */
293
294
295/** @name Internal Root Hub Operations, Structures and Constants.
296 * @{
297 */
298
299/**
300 * Per transfer type statistics.
301 */
302typedef struct VUSBROOTHUBTYPESTATS
303{
304 STAMCOUNTER StatUrbsSubmitted;
305 STAMCOUNTER StatUrbsFailed;
306 STAMCOUNTER StatUrbsCancelled;
307
308 STAMCOUNTER StatReqBytes;
309 STAMCOUNTER StatReqReadBytes;
310 STAMCOUNTER StatReqWriteBytes;
311
312 STAMCOUNTER StatActBytes;
313 STAMCOUNTER StatActReadBytes;
314 STAMCOUNTER StatActWriteBytes;
315} VUSBROOTHUBTYPESTATS, *PVUSBROOTHUBTYPESTATS;
316
317
318
319/** The address hash table size. */
320#define VUSB_ADDR_HASHSZ 5
321
322/**
323 * The instance data of a root hub driver.
324 *
325 * This extends the generic VUSB hub.
326 *
327 * @implements VUSBIROOTHUBCONNECTOR
328 */
329typedef struct VUSBROOTHUB
330{
331 /** The HUB.
332 * @todo remove this? */
333 VUSBHUB Hub;
334 /** Address hash table. */
335 PVUSBDEV apAddrHash[VUSB_ADDR_HASHSZ];
336 /** List of async URBs. */
337 PVUSBURB pAsyncUrbHead;
338 /** The default address. */
339 PVUSBDEV pDefaultAddress;
340
341 /** Pointer to the driver instance. */
342 PPDMDRVINS pDrvIns;
343 /** Pointer to the root hub port interface we're attached to. */
344 PVUSBIROOTHUBPORT pIRhPort;
345 /** Connector interface exposed upwards. */
346 VUSBIROOTHUBCONNECTOR IRhConnector;
347
348 /** Chain of devices attached to this hub. */
349 PVUSBDEV pDevices;
350 /** Availability Bitmap. */
351 VUSBPORTBITMAP Bitmap;
352
353 /** Critical section protecting the free list. */
354 RTCRITSECT CritSect;
355 /** Chain of free URBs. (Singly linked) */
356 PVUSBURB pFreeUrbs;
357 /** The number of URBs in the pool. */
358 uint32_t cUrbsInPool;
359 /** Version of the attached Host Controller. */
360 uint32_t fHcVersions;
361#ifdef VBOX_WITH_STATISTICS
362 VUSBROOTHUBTYPESTATS Total;
363 VUSBROOTHUBTYPESTATS aTypes[VUSBXFERTYPE_MSG];
364 STAMCOUNTER StatIsocReqPkts;
365 STAMCOUNTER StatIsocReqReadPkts;
366 STAMCOUNTER StatIsocReqWritePkts;
367 STAMCOUNTER StatIsocActPkts;
368 STAMCOUNTER StatIsocActReadPkts;
369 STAMCOUNTER StatIsocActWritePkts;
370 struct
371 {
372 STAMCOUNTER Pkts;
373 STAMCOUNTER Ok;
374 STAMCOUNTER Ok0;
375 STAMCOUNTER DataUnderrun;
376 STAMCOUNTER DataUnderrun0;
377 STAMCOUNTER DataOverrun;
378 STAMCOUNTER NotAccessed;
379 STAMCOUNTER Misc;
380 STAMCOUNTER Bytes;
381 } aStatIsocDetails[8];
382
383 STAMPROFILE StatReapAsyncUrbs;
384 STAMPROFILE StatSubmitUrb;
385#endif
386} VUSBROOTHUB;
387
388/** Converts a pointer to VUSBROOTHUB::IRhConnector to a PVUSBROOTHUB. */
389#define VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface) (PVUSBROOTHUB)( (uintptr_t)(pInterface) - RT_OFFSETOF(VUSBROOTHUB, IRhConnector) )
390
391
392/* @} */
393
394
395
396/** @name Internal URB Operations, Structures and Constants.
397 * @{ */
398int vusbUrbSubmit(PVUSBURB pUrb);
399void vusbUrbTrace(PVUSBURB pUrb, const char *pszMsg, bool fComplete);
400void vusbUrbDoReapAsync(PVUSBURB pHead, RTMSINTERVAL cMillies);
401void vusbUrbCancel(PVUSBURB pUrb);
402void vusbUrbRipe(PVUSBURB pUrb);
403void vusbUrbCompletionRh(PVUSBURB pUrb);
404
405void vusbUrbCompletionReadAhead(PVUSBURB pUrb);
406void vusbReadAheadStart(PVUSBDEV pDev, PVUSBPIPE pPipe);
407void vusbReadAheadStop(void *pvReadAheadArgs);
408int vusbUrbQueueAsyncRh(PVUSBURB pUrb);
409int vusbUrbSubmitBufferedRead(PVUSBURB pUrb, PVUSBPIPE pPipe);
410PVUSBURB vusbRhNewUrb(PVUSBROOTHUB pRh, uint8_t DstAddress, uint32_t cbData, uint32_t cTds);
411
412
413DECLINLINE(void) vusbUrbUnlink(PVUSBURB pUrb)
414{
415 *pUrb->VUsb.ppPrev = pUrb->VUsb.pNext;
416 if (pUrb->VUsb.pNext)
417 pUrb->VUsb.pNext->VUsb.ppPrev = pUrb->VUsb.ppPrev;
418 pUrb->VUsb.pNext = NULL;
419 pUrb->VUsb.ppPrev = NULL;
420}
421
422/** @def vusbUrbAssert
423 * Asserts that a URB is valid.
424 */
425#ifdef VBOX_STRICT
426# define vusbUrbAssert(pUrb) do { \
427 AssertMsg(VALID_PTR((pUrb)), ("%p\n", (pUrb))); \
428 AssertMsg((pUrb)->u32Magic == VUSBURB_MAGIC, ("%#x", (pUrb)->u32Magic)); \
429 AssertMsg((pUrb)->enmState > VUSBURBSTATE_INVALID && (pUrb)->enmState < VUSBURBSTATE_END, \
430 ("%d\n", (pUrb)->enmState)); \
431 } while (0)
432#else
433# define vusbUrbAssert(pUrb) do {} while (0)
434#endif
435
436/** @} */
437
438
439
440
441/**
442 * Addresses are between 0 and 127 inclusive
443 */
444DECLINLINE(uint8_t) vusbHashAddress(uint8_t Address)
445{
446 uint8_t u8Hash = Address;
447 u8Hash ^= (Address >> 2);
448 u8Hash ^= (Address >> 3);
449 u8Hash %= VUSB_ADDR_HASHSZ;
450 return u8Hash;
451}
452
453
454/**
455 * Gets the roothub of a device.
456 *
457 * @returns Pointer to the roothub instance the device is attached to.
458 * @returns NULL if not attached to any hub.
459 * @param pDev Pointer to the device in question.
460 */
461DECLINLINE(PVUSBROOTHUB) vusbDevGetRh(PVUSBDEV pDev)
462{
463 if (!pDev->pHub)
464 return NULL;
465 return pDev->pHub->pRootHub;
466}
467
468
469
470/** Strings for the CTLSTAGE enum values. */
471extern const char * const g_apszCtlStates[4];
472/** Default message pipe. */
473extern const VUSBDESCENDPOINTEX g_Endpoint0;
474/** Default configuration. */
475extern const VUSBDESCCONFIGEX g_Config0;
476
477RT_C_DECLS_END
478#endif
479
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