VirtualBox

source: vbox/trunk/src/VBox/Devices/USB/VUSBDevice.cpp@ 93974

最後變更 在這個檔案從93974是 93974,由 vboxsync 提交於 3 年 前

Devices/USB: Fix for regression introduced with r150168 where a guest failed to enumerate USB devices if more than one device was on the bus when the VM was powered on. Simplify the code even more to not require any lists for devices in the default state, bugref:10196

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 62.3 KB
 
1/* $Id: VUSBDevice.cpp 93974 2022-02-28 12:03:21Z vboxsync $ */
2/** @file
3 * Virtual USB - Device.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DRV_VUSB
23#include <VBox/vmm/pdm.h>
24#include <VBox/vmm/vmapi.h>
25#include <VBox/err.h>
26#include <VBox/log.h>
27#include <iprt/alloc.h>
28#include <iprt/time.h>
29#include <iprt/thread.h>
30#include <iprt/semaphore.h>
31#include <iprt/string.h>
32#include <iprt/assert.h>
33#include <iprt/asm.h>
34#include "VUSBInternal.h"
35
36#include "VUSBSniffer.h"
37
38
39/*********************************************************************************************************************************
40* Structures and Typedefs *
41*********************************************************************************************************************************/
42/**
43 * Argument package of vusbDevResetThread().
44 */
45typedef struct vusb_reset_args
46{
47 /** Pointer to the device which is being reset. */
48 PVUSBDEV pDev;
49 /** The reset return code. */
50 int rc;
51 /** Pointer to the completion callback. */
52 PFNVUSBRESETDONE pfnDone;
53 /** User argument to pfnDone. */
54 void *pvUser;
55} VUSBRESETARGS, *PVUSBRESETARGS;
56
57
58/*********************************************************************************************************************************
59* Global Variables *
60*********************************************************************************************************************************/
61/** Default message pipe. */
62const VUSBDESCENDPOINTEX g_Endpoint0 =
63{
64 {
65 /* .bLength = */ VUSB_DT_ENDPOINT_MIN_LEN,
66 /* .bDescriptorType = */ VUSB_DT_ENDPOINT,
67 /* .bEndpointAddress = */ 0,
68 /* .bmAttributes = */ 0,
69 /* .wMaxPacketSize = */ 64,
70 /* .bInterval = */ 0
71 },
72 NULL
73};
74
75/** Default configuration. */
76const VUSBDESCCONFIGEX g_Config0 =
77{
78 {
79 /* .bLength = */ VUSB_DT_CONFIG_MIN_LEN,
80 /* .bDescriptorType = */ VUSB_DT_CONFIG,
81 /* .WTotalLength = */ 0, /* (auto-calculated) */
82 /* .bNumInterfaces = */ 0,
83 /* .bConfigurationValue =*/ 0,
84 /* .iConfiguration = */ 0,
85 /* .bmAttributes = */ 0x80,
86 /* .MaxPower = */ 14
87 },
88 NULL,
89 NULL
90};
91
92
93
94static PCVUSBDESCCONFIGEX vusbDevFindCfgDesc(PVUSBDEV pDev, int iCfg)
95{
96 if (iCfg == 0)
97 return &g_Config0;
98
99 for (unsigned i = 0; i < pDev->pDescCache->pDevice->bNumConfigurations; i++)
100 if (pDev->pDescCache->paConfigs[i].Core.bConfigurationValue == iCfg)
101 return &pDev->pDescCache->paConfigs[i];
102 return NULL;
103}
104
105static PVUSBINTERFACESTATE vusbDevFindIfState(PVUSBDEV pDev, int iIf)
106{
107 for (unsigned i = 0; i < pDev->pCurCfgDesc->Core.bNumInterfaces; i++)
108 if (pDev->paIfStates[i].pIf->paSettings[0].Core.bInterfaceNumber == iIf)
109 return &pDev->paIfStates[i];
110 return NULL;
111}
112
113static PCVUSBDESCINTERFACEEX vusbDevFindAltIfDesc(PCVUSBINTERFACESTATE pIfState, int iAlt)
114{
115 for (uint32_t i = 0; i < pIfState->pIf->cSettings; i++)
116 if (pIfState->pIf->paSettings[i].Core.bAlternateSetting == iAlt)
117 return &pIfState->pIf->paSettings[i];
118 return NULL;
119}
120
121void vusbDevMapEndpoint(PVUSBDEV pDev, PCVUSBDESCENDPOINTEX pEndPtDesc)
122{
123 uint8_t i8Addr = pEndPtDesc->Core.bEndpointAddress & 0xF;
124 PVUSBPIPE pPipe = &pDev->aPipes[i8Addr];
125 LogFlow(("vusbDevMapEndpoint: pDev=%p[%s] pEndPtDesc=%p{.bEndpointAddress=%#x, .bmAttributes=%#x} p=%p stage %s->SETUP\n",
126 pDev, pDev->pUsbIns->pszName, pEndPtDesc, pEndPtDesc->Core.bEndpointAddress, pEndPtDesc->Core.bmAttributes,
127 pPipe, g_apszCtlStates[pPipe->pCtrl ? pPipe->pCtrl->enmStage : 3]));
128
129 if ((pEndPtDesc->Core.bmAttributes & 0x3) == 0)
130 {
131 Log(("vusb: map message pipe on address %u\n", i8Addr));
132 pPipe->in = pEndPtDesc;
133 pPipe->out = pEndPtDesc;
134 }
135 else if (pEndPtDesc->Core.bEndpointAddress & 0x80)
136 {
137 Log(("vusb: map input pipe on address %u\n", i8Addr));
138 pPipe->in = pEndPtDesc;
139 }
140 else
141 {
142 Log(("vusb: map output pipe on address %u\n", i8Addr));
143 pPipe->out = pEndPtDesc;
144 }
145
146 if (pPipe->pCtrl)
147 {
148 vusbMsgFreeExtraData(pPipe->pCtrl);
149 pPipe->pCtrl = NULL;
150 }
151}
152
153static void unmap_endpoint(PVUSBDEV pDev, PCVUSBDESCENDPOINTEX pEndPtDesc)
154{
155 uint8_t EndPt = pEndPtDesc->Core.bEndpointAddress & 0xF;
156 PVUSBPIPE pPipe = &pDev->aPipes[EndPt];
157 LogFlow(("unmap_endpoint: pDev=%p[%s] pEndPtDesc=%p{.bEndpointAddress=%#x, .bmAttributes=%#x} p=%p stage %s->SETUP\n",
158 pDev, pDev->pUsbIns->pszName, pEndPtDesc, pEndPtDesc->Core.bEndpointAddress, pEndPtDesc->Core.bmAttributes,
159 pPipe, g_apszCtlStates[pPipe->pCtrl ? pPipe->pCtrl->enmStage : 3]));
160
161 if ((pEndPtDesc->Core.bmAttributes & 0x3) == 0)
162 {
163 Log(("vusb: unmap MSG pipe from address %u (%#x)\n", EndPt, pEndPtDesc->Core.bEndpointAddress));
164 pPipe->in = NULL;
165 pPipe->out = NULL;
166 }
167 else if (pEndPtDesc->Core.bEndpointAddress & 0x80)
168 {
169 Log(("vusb: unmap IN pipe from address %u (%#x)\n", EndPt, pEndPtDesc->Core.bEndpointAddress));
170 pPipe->in = NULL;
171 }
172 else
173 {
174 Log(("vusb: unmap OUT pipe from address %u (%#x)\n", EndPt, pEndPtDesc->Core.bEndpointAddress));
175 pPipe->out = NULL;
176 }
177
178 if (pPipe->pCtrl)
179 {
180 vusbMsgFreeExtraData(pPipe->pCtrl);
181 pPipe->pCtrl = NULL;
182 }
183}
184
185static void map_interface(PVUSBDEV pDev, PCVUSBDESCINTERFACEEX pIfDesc)
186{
187 LogFlow(("map_interface: pDev=%p[%s] pIfDesc=%p:{.iInterface=%d, .bAlternateSetting=%d}\n",
188 pDev, pDev->pUsbIns->pszName, pIfDesc, pIfDesc->Core.iInterface, pIfDesc->Core.bAlternateSetting));
189
190 for (unsigned i = 0; i < pIfDesc->Core.bNumEndpoints; i++)
191 {
192 if ((pIfDesc->paEndpoints[i].Core.bEndpointAddress & 0xF) == VUSB_PIPE_DEFAULT)
193 Log(("vusb: Endpoint 0x%x on interface %u.%u tried to override the default message pipe!!!\n",
194 pIfDesc->paEndpoints[i].Core.bEndpointAddress, pIfDesc->Core.bInterfaceNumber, pIfDesc->Core.bAlternateSetting));
195 else
196 vusbDevMapEndpoint(pDev, &pIfDesc->paEndpoints[i]);
197 }
198}
199
200
201/**
202 * Worker that resets the pipe data on select config and detach.
203 *
204 * This leaves the critical section unmolested
205 *
206 * @param pPipe The pipe which data should be reset.
207 */
208static void vusbDevResetPipeData(PVUSBPIPE pPipe)
209{
210 vusbMsgFreeExtraData(pPipe->pCtrl);
211 pPipe->pCtrl = NULL;
212
213 RT_ZERO(pPipe->in);
214 RT_ZERO(pPipe->out);
215 pPipe->async = 0;
216}
217
218
219bool vusbDevDoSelectConfig(PVUSBDEV pDev, PCVUSBDESCCONFIGEX pCfgDesc)
220{
221 LogFlow(("vusbDevDoSelectConfig: pDev=%p[%s] pCfgDesc=%p:{.iConfiguration=%d}\n",
222 pDev, pDev->pUsbIns->pszName, pCfgDesc, pCfgDesc->Core.iConfiguration));
223
224 /*
225 * Clean up all pipes and interfaces.
226 */
227 unsigned i;
228 for (i = 0; i < VUSB_PIPE_MAX; i++)
229 if (i != VUSB_PIPE_DEFAULT)
230 vusbDevResetPipeData(&pDev->aPipes[i]);
231 memset(pDev->paIfStates, 0, pCfgDesc->Core.bNumInterfaces * sizeof(pDev->paIfStates[0]));
232
233 /*
234 * Map in the default setting for every interface.
235 */
236 for (i = 0; i < pCfgDesc->Core.bNumInterfaces; i++)
237 {
238 PCVUSBINTERFACE pIf;
239 struct vusb_interface_state *pIfState;
240
241 pIf = &pCfgDesc->paIfs[i];
242 pIfState = &pDev->paIfStates[i];
243 pIfState->pIf = pIf;
244
245 /*
246 * Find the 0 setting, if it is not present we just use
247 * the lowest numbered one.
248 */
249 for (uint32_t j = 0; j < pIf->cSettings; j++)
250 {
251 if ( !pIfState->pCurIfDesc
252 || pIf->paSettings[j].Core.bAlternateSetting < pIfState->pCurIfDesc->Core.bAlternateSetting)
253 pIfState->pCurIfDesc = &pIf->paSettings[j];
254 if (pIfState->pCurIfDesc->Core.bAlternateSetting == 0)
255 break;
256 }
257
258 if (pIfState->pCurIfDesc)
259 map_interface(pDev, pIfState->pCurIfDesc);
260 }
261
262 pDev->pCurCfgDesc = pCfgDesc;
263
264 if (pCfgDesc->Core.bmAttributes & 0x40)
265 pDev->u16Status |= (1 << VUSB_DEV_SELF_POWERED);
266 else
267 pDev->u16Status &= ~(1 << VUSB_DEV_SELF_POWERED);
268
269 return true;
270}
271
272/**
273 * Standard device request: SET_CONFIGURATION
274 * @returns success indicator.
275 */
276static bool vusbDevStdReqSetConfig(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, uint8_t *pbBuf, uint32_t *pcbBuf)
277{
278 RT_NOREF(EndPt, pbBuf, pcbBuf);
279 unsigned iCfg = pSetup->wValue & 0xff;
280
281 if ((pSetup->bmRequestType & VUSB_RECIP_MASK) != VUSB_TO_DEVICE)
282 {
283 Log(("vusb: error: %s: SET_CONFIGURATION - invalid request (dir) !!!\n", pDev->pUsbIns->pszName));
284 return false;
285 }
286
287 /*
288 * Check that the device is in a valid state.
289 * (The caller has already checked that it's not being reset.)
290 */
291 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
292 if (enmState == VUSB_DEVICE_STATE_DEFAULT)
293 {
294 LogFlow(("vusbDevStdReqSetConfig: %s: default dev state !!?\n", pDev->pUsbIns->pszName));
295 return false;
296 }
297
298 PCVUSBDESCCONFIGEX pNewCfgDesc = vusbDevFindCfgDesc(pDev, iCfg);
299 if (!pNewCfgDesc)
300 {
301 Log(("vusb: error: %s: config %i not found !!!\n", pDev->pUsbIns->pszName, iCfg));
302 return false;
303 }
304
305 if (iCfg == 0)
306 vusbDevSetState(pDev, VUSB_DEVICE_STATE_ADDRESS);
307 else
308 vusbDevSetState(pDev, VUSB_DEVICE_STATE_CONFIGURED);
309 if (pDev->pUsbIns->pReg->pfnUsbSetConfiguration)
310 {
311 RTCritSectEnter(&pDev->pHub->pRootHub->CritSectDevices);
312 int rc = vusbDevIoThreadExecSync(pDev, (PFNRT)pDev->pUsbIns->pReg->pfnUsbSetConfiguration, 5,
313 pDev->pUsbIns, pNewCfgDesc->Core.bConfigurationValue,
314 pDev->pCurCfgDesc, pDev->paIfStates, pNewCfgDesc);
315 RTCritSectLeave(&pDev->pHub->pRootHub->CritSectDevices);
316 if (RT_FAILURE(rc))
317 {
318 Log(("vusb: error: %s: failed to set config %i (%Rrc) !!!\n", pDev->pUsbIns->pszName, iCfg, rc));
319 return false;
320 }
321 }
322 Log(("vusb: %p[%s]: SET_CONFIGURATION: Selected config %u\n", pDev, pDev->pUsbIns->pszName, iCfg));
323 return vusbDevDoSelectConfig(pDev, pNewCfgDesc);
324}
325
326
327/**
328 * Standard device request: GET_CONFIGURATION
329 * @returns success indicator.
330 */
331static bool vusbDevStdReqGetConfig(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, uint8_t *pbBuf, uint32_t *pcbBuf)
332{
333 RT_NOREF(EndPt);
334 if ((pSetup->bmRequestType & VUSB_RECIP_MASK) != VUSB_TO_DEVICE)
335 {
336 Log(("vusb: error: %s: GET_CONFIGURATION - invalid request (dir) !!!\n", pDev->pUsbIns->pszName));
337 return false;
338 }
339
340 /*
341 * Check that the device is in a valid state.
342 * (The caller has already checked that it's not being reset.)
343 */
344 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
345 if ( enmState != VUSB_DEVICE_STATE_CONFIGURED
346 && enmState != VUSB_DEVICE_STATE_ADDRESS)
347 {
348 LogFlow(("vusbDevStdReqGetConfig: error: %s: invalid device state %d!!!\n", pDev->pUsbIns->pszName, enmState));
349 return false;
350 }
351
352 if (*pcbBuf < 1)
353 {
354 LogFlow(("vusbDevStdReqGetConfig: %s: no space for data!\n", pDev->pUsbIns->pszName));
355 return true;
356 }
357
358 uint8_t iCfg;
359 if (enmState == VUSB_DEVICE_STATE_ADDRESS)
360 iCfg = 0;
361 else
362 iCfg = pDev->pCurCfgDesc->Core.bConfigurationValue;
363
364 *pbBuf = iCfg;
365 *pcbBuf = 1;
366 LogFlow(("vusbDevStdReqGetConfig: %s: returns iCfg=%d\n", pDev->pUsbIns->pszName, iCfg));
367 return true;
368}
369
370/**
371 * Standard device request: GET_INTERFACE
372 * @returns success indicator.
373 */
374static bool vusbDevStdReqGetInterface(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, uint8_t *pbBuf, uint32_t *pcbBuf)
375{
376 RT_NOREF(EndPt);
377 if ((pSetup->bmRequestType & VUSB_RECIP_MASK) != VUSB_TO_INTERFACE)
378 {
379 Log(("vusb: error: %s: GET_INTERFACE - invalid request (dir) !!!\n", pDev->pUsbIns->pszName));
380 return false;
381 }
382
383 /*
384 * Check that the device is in a valid state.
385 * (The caller has already checked that it's not being reset.)
386 */
387 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
388 if (enmState != VUSB_DEVICE_STATE_CONFIGURED)
389 {
390 LogFlow(("vusbDevStdReqGetInterface: error: %s: invalid device state %d!!!\n", pDev->pUsbIns->pszName, enmState));
391 return false;
392 }
393
394 if (*pcbBuf < 1)
395 {
396 LogFlow(("vusbDevStdReqGetInterface: %s: no space for data!\n", pDev->pUsbIns->pszName));
397 return true;
398 }
399
400 for (unsigned i = 0; i < pDev->pCurCfgDesc->Core.bNumInterfaces; i++)
401 {
402 PCVUSBDESCINTERFACEEX pIfDesc = pDev->paIfStates[i].pCurIfDesc;
403 if ( pIfDesc
404 && pSetup->wIndex == pIfDesc->Core.bInterfaceNumber)
405 {
406 *pbBuf = pIfDesc->Core.bAlternateSetting;
407 *pcbBuf = 1;
408 Log(("vusb: %s: GET_INTERFACE: %u.%u\n", pDev->pUsbIns->pszName, pIfDesc->Core.bInterfaceNumber, *pbBuf));
409 return true;
410 }
411 }
412
413 Log(("vusb: error: %s: GET_INTERFACE - unknown iface %u !!!\n", pDev->pUsbIns->pszName, pSetup->wIndex));
414 return false;
415}
416
417/**
418 * Standard device request: SET_INTERFACE
419 * @returns success indicator.
420 */
421static bool vusbDevStdReqSetInterface(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, uint8_t *pbBuf, uint32_t *pcbBuf)
422{
423 RT_NOREF(EndPt, pbBuf, pcbBuf);
424 if ((pSetup->bmRequestType & VUSB_RECIP_MASK) != VUSB_TO_INTERFACE)
425 {
426 Log(("vusb: error: %s: SET_INTERFACE - invalid request (dir) !!!\n", pDev->pUsbIns->pszName));
427 return false;
428 }
429
430 /*
431 * Check that the device is in a valid state.
432 * (The caller has already checked that it's not being reset.)
433 */
434 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
435 if (enmState != VUSB_DEVICE_STATE_CONFIGURED)
436 {
437 LogFlow(("vusbDevStdReqSetInterface: error: %s: invalid device state %d !!!\n", pDev->pUsbIns->pszName, enmState));
438 return false;
439 }
440
441 /*
442 * Find the interface.
443 */
444 uint8_t iIf = pSetup->wIndex;
445 PVUSBINTERFACESTATE pIfState = vusbDevFindIfState(pDev, iIf);
446 if (!pIfState)
447 {
448 LogFlow(("vusbDevStdReqSetInterface: error: %s: couldn't find interface %u !!!\n", pDev->pUsbIns->pszName, iIf));
449 return false;
450 }
451 uint8_t iAlt = pSetup->wValue;
452 PCVUSBDESCINTERFACEEX pIfDesc = vusbDevFindAltIfDesc(pIfState, iAlt);
453 if (!pIfDesc)
454 {
455 LogFlow(("vusbDevStdReqSetInterface: error: %s: couldn't find alt interface %u.%u !!!\n", pDev->pUsbIns->pszName, iIf, iAlt));
456 return false;
457 }
458
459 if (pDev->pUsbIns->pReg->pfnUsbSetInterface)
460 {
461 RTCritSectEnter(&pDev->pHub->pRootHub->CritSectDevices);
462 int rc = vusbDevIoThreadExecSync(pDev, (PFNRT)pDev->pUsbIns->pReg->pfnUsbSetInterface, 3, pDev->pUsbIns, iIf, iAlt);
463 RTCritSectLeave(&pDev->pHub->pRootHub->CritSectDevices);
464 if (RT_FAILURE(rc))
465 {
466 LogFlow(("vusbDevStdReqSetInterface: error: %s: couldn't find alt interface %u.%u (%Rrc)\n", pDev->pUsbIns->pszName, iIf, iAlt, rc));
467 return false;
468 }
469 }
470
471 for (unsigned i = 0; i < pIfState->pCurIfDesc->Core.bNumEndpoints; i++)
472 unmap_endpoint(pDev, &pIfState->pCurIfDesc->paEndpoints[i]);
473
474 Log(("vusb: SET_INTERFACE: Selected %u.%u\n", iIf, iAlt));
475
476 map_interface(pDev, pIfDesc);
477 pIfState->pCurIfDesc = pIfDesc;
478
479 return true;
480}
481
482/**
483 * Standard device request: SET_ADDRESS
484 * @returns success indicator.
485 */
486static bool vusbDevStdReqSetAddress(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, uint8_t *pbBuf, uint32_t *pcbBuf)
487{
488 RT_NOREF(EndPt, pbBuf, pcbBuf);
489 if ((pSetup->bmRequestType & VUSB_RECIP_MASK) != VUSB_TO_DEVICE)
490 {
491 Log(("vusb: error: %s: SET_ADDRESS - invalid request (dir) !!!\n", pDev->pUsbIns->pszName));
492 return false;
493 }
494
495 /*
496 * Check that the device is in a valid state.
497 * (The caller has already checked that it's not being reset.)
498 */
499 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
500 if ( enmState != VUSB_DEVICE_STATE_DEFAULT
501 && enmState != VUSB_DEVICE_STATE_ADDRESS)
502 {
503 LogFlow(("vusbDevStdReqSetAddress: error: %s: invalid device state %d !!!\n", pDev->pUsbIns->pszName, enmState));
504 return false;
505 }
506
507 pDev->u8NewAddress = pSetup->wValue;
508 return true;
509}
510
511/**
512 * Standard device request: CLEAR_FEATURE
513 * @returns success indicator.
514 *
515 * @remark This is only called for VUSB_TO_ENDPOINT && ep == 0 && wValue == ENDPOINT_HALT.
516 * All other cases of CLEAR_FEATURE is handled in the normal async/sync manner.
517 */
518static bool vusbDevStdReqClearFeature(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, uint8_t *pbBuf, uint32_t *pcbBuf)
519{
520 RT_NOREF(pbBuf, pcbBuf);
521 switch (pSetup->bmRequestType & VUSB_RECIP_MASK)
522 {
523 case VUSB_TO_DEVICE:
524 Log(("vusb: ClearFeature: dev(%u): selector=%u\n", pSetup->wIndex, pSetup->wValue));
525 break;
526 case VUSB_TO_INTERFACE:
527 Log(("vusb: ClearFeature: iface(%u): selector=%u\n", pSetup->wIndex, pSetup->wValue));
528 break;
529 case VUSB_TO_ENDPOINT:
530 Log(("vusb: ClearFeature: ep(%u): selector=%u\n", pSetup->wIndex, pSetup->wValue));
531 if ( !EndPt /* Default control pipe only */
532 && pSetup->wValue == 0 /* ENDPOINT_HALT */
533 && pDev->pUsbIns->pReg->pfnUsbClearHaltedEndpoint)
534 {
535 RTCritSectEnter(&pDev->pHub->pRootHub->CritSectDevices);
536 int rc = vusbDevIoThreadExecSync(pDev, (PFNRT)pDev->pUsbIns->pReg->pfnUsbClearHaltedEndpoint,
537 2, pDev->pUsbIns, pSetup->wIndex);
538 RTCritSectLeave(&pDev->pHub->pRootHub->CritSectDevices);
539 return RT_SUCCESS(rc);
540 }
541 break;
542 default:
543 AssertMsgFailed(("VUSB_TO_OTHER!\n"));
544 break;
545 }
546
547 AssertMsgFailed(("Invalid safe check !!!\n"));
548 return false;
549}
550
551/**
552 * Standard device request: SET_FEATURE
553 * @returns success indicator.
554 */
555static bool vusbDevStdReqSetFeature(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, uint8_t *pbBuf, uint32_t *pcbBuf)
556{
557 RT_NOREF(pDev, EndPt, pbBuf, pcbBuf);
558 switch (pSetup->bmRequestType & VUSB_RECIP_MASK)
559 {
560 case VUSB_TO_DEVICE:
561 Log(("vusb: SetFeature: dev(%u): selector=%u\n",
562 pSetup->wIndex, pSetup->wValue));
563 break;
564 case VUSB_TO_INTERFACE:
565 Log(("vusb: SetFeature: if(%u): selector=%u\n",
566 pSetup->wIndex, pSetup->wValue));
567 break;
568 case VUSB_TO_ENDPOINT:
569 Log(("vusb: SetFeature: ep(%u): selector=%u\n",
570 pSetup->wIndex, pSetup->wValue));
571 break;
572 default:
573 AssertMsgFailed(("VUSB_TO_OTHER!\n"));
574 return false;
575 }
576 AssertMsgFailed(("This stuff is bogus\n"));
577 return false;
578}
579
580static bool vusbDevStdReqGetStatus(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, uint8_t *pbBuf, uint32_t *pcbBuf)
581{
582 RT_NOREF(EndPt);
583 if (*pcbBuf != 2)
584 {
585 LogFlow(("vusbDevStdReqGetStatus: %s: buffer is too small! (%d)\n", pDev->pUsbIns->pszName, *pcbBuf));
586 return false;
587 }
588
589 uint16_t u16Status;
590 switch (pSetup->bmRequestType & VUSB_RECIP_MASK)
591 {
592 case VUSB_TO_DEVICE:
593 u16Status = pDev->u16Status;
594 LogFlow(("vusbDevStdReqGetStatus: %s: device status %#x (%d)\n", pDev->pUsbIns->pszName, u16Status, u16Status));
595 break;
596 case VUSB_TO_INTERFACE:
597 u16Status = 0;
598 LogFlow(("vusbDevStdReqGetStatus: %s: bogus interface status request!!\n", pDev->pUsbIns->pszName));
599 break;
600 case VUSB_TO_ENDPOINT:
601 u16Status = 0;
602 LogFlow(("vusbDevStdReqGetStatus: %s: bogus endpoint status request!!\n", pDev->pUsbIns->pszName));
603 break;
604 default:
605 AssertMsgFailed(("VUSB_TO_OTHER!\n"));
606 return false;
607 }
608
609 *(uint16_t *)pbBuf = u16Status;
610 return true;
611}
612
613
614/**
615 * Finds a cached string.
616 *
617 * @returns Pointer to the cached string if found. NULL if not.
618 * @param paLanguages The languages to search.
619 * @param cLanguages The number of languages in the table.
620 * @param idLang The language ID.
621 * @param iString The string index.
622 */
623static PCPDMUSBDESCCACHESTRING FindCachedString(PCPDMUSBDESCCACHELANG paLanguages, unsigned cLanguages,
624 uint16_t idLang, uint8_t iString)
625{
626 /** @todo binary lookups! */
627 unsigned iCurLang = cLanguages;
628 while (iCurLang-- > 0)
629 if (paLanguages[iCurLang].idLang == idLang)
630 {
631 PCPDMUSBDESCCACHESTRING paStrings = paLanguages[iCurLang].paStrings;
632 unsigned iCurStr = paLanguages[iCurLang].cStrings;
633 while (iCurStr-- > 0)
634 if (paStrings[iCurStr].idx == iString)
635 return &paStrings[iCurStr];
636 break;
637 }
638 return NULL;
639}
640
641
642/** Macro for copying descriptor data. */
643#define COPY_DATA(pbDst, cbLeft, pvSrc, cbSrc) \
644 do { \
645 uint32_t cbSrc_ = cbSrc; \
646 uint32_t cbCopy = RT_MIN(cbLeft, cbSrc_); \
647 if (cbCopy) \
648 memcpy(pbBuf, pvSrc, cbCopy); \
649 cbLeft -= cbCopy; \
650 if (!cbLeft) \
651 return; \
652 pbBuf += cbCopy; \
653 } while (0)
654
655/**
656 * Internal function for reading the language IDs.
657 */
658static void ReadCachedStringDesc(PCPDMUSBDESCCACHESTRING pString, uint8_t *pbBuf, uint32_t *pcbBuf)
659{
660 uint32_t cbLeft = *pcbBuf;
661
662 RTUTF16 wsz[128]; /* 128-1 => bLength=0xff */
663 PRTUTF16 pwsz = wsz;
664 size_t cwc;
665 int rc = RTStrToUtf16Ex(pString->psz, RT_ELEMENTS(wsz) - 1, &pwsz, RT_ELEMENTS(wsz), &cwc);
666 if (RT_FAILURE(rc))
667 {
668 AssertRC(rc);
669 wsz[0] = 'e';
670 wsz[1] = 'r';
671 wsz[2] = 'r';
672 cwc = 3;
673 }
674
675 VUSBDESCSTRING StringDesc;
676 StringDesc.bLength = (uint8_t)(sizeof(StringDesc) + cwc * sizeof(RTUTF16));
677 StringDesc.bDescriptorType = VUSB_DT_STRING;
678 COPY_DATA(pbBuf, cbLeft, &StringDesc, sizeof(StringDesc));
679 COPY_DATA(pbBuf, cbLeft, wsz, (uint32_t)cwc * sizeof(RTUTF16));
680
681 /* updated the size of the output buffer. */
682 *pcbBuf -= cbLeft;
683}
684
685
686/**
687 * Internal function for reading the language IDs.
688 */
689static void ReadCachedLangIdDesc(PCPDMUSBDESCCACHELANG paLanguages, unsigned cLanguages,
690 uint8_t *pbBuf, uint32_t *pcbBuf)
691{
692 uint32_t cbLeft = *pcbBuf;
693
694 VUSBDESCLANGID LangIdDesc;
695 size_t cbDesc = sizeof(LangIdDesc) + cLanguages * sizeof(paLanguages[0].idLang);
696 LangIdDesc.bLength = (uint8_t)RT_MIN(0xff, cbDesc);
697 LangIdDesc.bDescriptorType = VUSB_DT_STRING;
698 COPY_DATA(pbBuf, cbLeft, &LangIdDesc, sizeof(LangIdDesc));
699
700 unsigned iLanguage = cLanguages;
701 while (iLanguage-- > 0)
702 COPY_DATA(pbBuf, cbLeft, &paLanguages[iLanguage].idLang, sizeof(paLanguages[iLanguage].idLang));
703
704 /* updated the size of the output buffer. */
705 *pcbBuf -= cbLeft;
706}
707
708
709/**
710 * Internal function which performs a descriptor read on the cached descriptors.
711 */
712static void ReadCachedConfigDesc(PCVUSBDESCCONFIGEX pCfgDesc, uint8_t *pbBuf, uint32_t *pcbBuf)
713{
714 uint32_t cbLeft = *pcbBuf;
715
716 /*
717 * Make a copy of the config descriptor and calculate the wTotalLength field.
718 */
719 VUSBDESCCONFIG CfgDesc;
720 memcpy(&CfgDesc, pCfgDesc, VUSB_DT_CONFIG_MIN_LEN);
721 uint32_t cbTotal = 0;
722 cbTotal += pCfgDesc->Core.bLength;
723 cbTotal += pCfgDesc->cbClass;
724 for (unsigned i = 0; i < pCfgDesc->Core.bNumInterfaces; i++)
725 {
726 PCVUSBINTERFACE pIf = &pCfgDesc->paIfs[i];
727 for (uint32_t j = 0; j < pIf->cSettings; j++)
728 {
729 cbTotal += pIf->paSettings[j].cbIAD;
730 cbTotal += pIf->paSettings[j].Core.bLength;
731 cbTotal += pIf->paSettings[j].cbClass;
732 for (unsigned k = 0; k < pIf->paSettings[j].Core.bNumEndpoints; k++)
733 {
734 cbTotal += pIf->paSettings[j].paEndpoints[k].Core.bLength;
735 cbTotal += pIf->paSettings[j].paEndpoints[k].cbSsepc;
736 cbTotal += pIf->paSettings[j].paEndpoints[k].cbClass;
737 }
738 }
739 }
740 CfgDesc.wTotalLength = RT_H2LE_U16(cbTotal);
741
742 /*
743 * Copy the config descriptor
744 */
745 COPY_DATA(pbBuf, cbLeft, &CfgDesc, VUSB_DT_CONFIG_MIN_LEN);
746 COPY_DATA(pbBuf, cbLeft, pCfgDesc->pvMore, pCfgDesc->Core.bLength - VUSB_DT_CONFIG_MIN_LEN);
747 COPY_DATA(pbBuf, cbLeft, pCfgDesc->pvClass, pCfgDesc->cbClass);
748
749 /*
750 * Copy out all the interfaces for this configuration
751 */
752 for (unsigned i = 0; i < pCfgDesc->Core.bNumInterfaces; i++)
753 {
754 PCVUSBINTERFACE pIf = &pCfgDesc->paIfs[i];
755 for (uint32_t j = 0; j < pIf->cSettings; j++)
756 {
757 PCVUSBDESCINTERFACEEX pIfDesc = &pIf->paSettings[j];
758
759 COPY_DATA(pbBuf, cbLeft, pIfDesc->pIAD, pIfDesc->cbIAD);
760 COPY_DATA(pbBuf, cbLeft, pIfDesc, VUSB_DT_INTERFACE_MIN_LEN);
761 COPY_DATA(pbBuf, cbLeft, pIfDesc->pvMore, pIfDesc->Core.bLength - VUSB_DT_INTERFACE_MIN_LEN);
762 COPY_DATA(pbBuf, cbLeft, pIfDesc->pvClass, pIfDesc->cbClass);
763
764 /*
765 * Copy out all the endpoints for this interface
766 */
767 for (unsigned k = 0; k < pIfDesc->Core.bNumEndpoints; k++)
768 {
769 VUSBDESCENDPOINT EndPtDesc;
770 memcpy(&EndPtDesc, &pIfDesc->paEndpoints[k], VUSB_DT_ENDPOINT_MIN_LEN);
771 EndPtDesc.wMaxPacketSize = RT_H2LE_U16(EndPtDesc.wMaxPacketSize);
772
773 COPY_DATA(pbBuf, cbLeft, &EndPtDesc, VUSB_DT_ENDPOINT_MIN_LEN);
774 COPY_DATA(pbBuf, cbLeft, pIfDesc->paEndpoints[k].pvMore, EndPtDesc.bLength - VUSB_DT_ENDPOINT_MIN_LEN);
775 COPY_DATA(pbBuf, cbLeft, pIfDesc->paEndpoints[k].pvSsepc, pIfDesc->paEndpoints[k].cbSsepc);
776 COPY_DATA(pbBuf, cbLeft, pIfDesc->paEndpoints[k].pvClass, pIfDesc->paEndpoints[k].cbClass);
777 }
778 }
779 }
780
781 /* updated the size of the output buffer. */
782 *pcbBuf -= cbLeft;
783}
784
785/**
786 * Internal function which performs a descriptor read on the cached descriptors.
787 */
788static void ReadCachedDeviceDesc(PCVUSBDESCDEVICE pDevDesc, uint8_t *pbBuf, uint32_t *pcbBuf)
789{
790 uint32_t cbLeft = *pcbBuf;
791
792 /*
793 * Duplicate the device description and update some fields we keep in cpu type.
794 */
795 Assert(sizeof(VUSBDESCDEVICE) == 18);
796 VUSBDESCDEVICE DevDesc = *pDevDesc;
797 DevDesc.bcdUSB = RT_H2LE_U16(DevDesc.bcdUSB);
798 DevDesc.idVendor = RT_H2LE_U16(DevDesc.idVendor);
799 DevDesc.idProduct = RT_H2LE_U16(DevDesc.idProduct);
800 DevDesc.bcdDevice = RT_H2LE_U16(DevDesc.bcdDevice);
801
802 COPY_DATA(pbBuf, cbLeft, &DevDesc, sizeof(DevDesc));
803 COPY_DATA(pbBuf, cbLeft, pDevDesc + 1, pDevDesc->bLength - sizeof(DevDesc));
804
805 /* updated the size of the output buffer. */
806 *pcbBuf -= cbLeft;
807}
808
809#undef COPY_DATA
810
811/**
812 * Checks whether a descriptor read can be satisfied by reading from the
813 * descriptor cache or has to be passed to the device.
814 * If we have descriptors cached, it is generally safe to satisfy descriptor reads
815 * from the cache. As usual, there is broken USB software and hardware out there
816 * and guests might try to read a nonexistent desciptor (out of range index for
817 * string or configuration descriptor) and rely on it not failing.
818 * Since we cannot very well guess if such invalid requests should really succeed,
819 * and what exactly should happen if they do, we pass such requests to the device.
820 * If the descriptor was cached because it was edited, and the guest bypasses the
821 * edited cache by reading a descriptor with an invalid index, it is probably
822 * best to smash the USB device with a large hammer.
823 *
824 * See @bugref{10016}.
825 *
826 * @returns false if request must be passed to device.
827 */
828bool vusbDevIsDescriptorInCache(PVUSBDEV pDev, PCVUSBSETUP pSetup)
829{
830 unsigned int iIndex = (pSetup->wValue & 0xff);
831 Assert(pSetup->bRequest == VUSB_REQ_GET_DESCRIPTOR);
832
833 if ((pSetup->bmRequestType & VUSB_RECIP_MASK) == VUSB_TO_DEVICE)
834 {
835 if (pDev->pDescCache->fUseCachedDescriptors)
836 {
837 switch (pSetup->wValue >> 8)
838 {
839 case VUSB_DT_DEVICE:
840 if (iIndex == 0)
841 return true;
842
843 LogRelMax(10, ("VUSB: %s: Warning: Reading device descriptor with non-zero index %u (wLength=%u), passing request to device\n",
844 pDev->pUsbIns->pszName, iIndex, pSetup->wLength));
845 break;
846
847 case VUSB_DT_CONFIG:
848 if (iIndex < pDev->pDescCache->pDevice->bNumConfigurations)
849 return true;
850
851 LogRelMax(10, ("VUSB: %s: Warning: Reading configuration descriptor invalid index %u (bNumConfigurations=%u, wLength=%u), passing request to device\n",
852 pDev->pUsbIns->pszName, iIndex, pDev->pDescCache->pDevice->bNumConfigurations, pSetup->wLength));
853 break;
854
855 case VUSB_DT_STRING:
856 if (pDev->pDescCache->fUseCachedStringsDescriptors)
857 {
858 if (pSetup->wIndex == 0) /* Language IDs. */
859 return true;
860
861 if (FindCachedString(pDev->pDescCache->paLanguages, pDev->pDescCache->cLanguages,
862 pSetup->wIndex, iIndex))
863 return true;
864 }
865 break;
866
867 default:
868 break;
869 }
870 Log(("VUSB: %s: Descriptor not cached: type=%u descidx=%u lang=%u len=%u, passing request to device\n",
871 pDev->pUsbIns->pszName, pSetup->wValue >> 8, iIndex, pSetup->wIndex, pSetup->wLength));
872 }
873 }
874 return false;
875}
876
877
878/**
879 * Standard device request: GET_DESCRIPTOR
880 * @returns success indicator.
881 */
882static bool vusbDevStdReqGetDescriptor(PVUSBDEV pDev, int EndPt, PVUSBSETUP pSetup, uint8_t *pbBuf, uint32_t *pcbBuf)
883{
884 RT_NOREF(EndPt);
885 if ((pSetup->bmRequestType & VUSB_RECIP_MASK) == VUSB_TO_DEVICE)
886 {
887 switch (pSetup->wValue >> 8)
888 {
889 case VUSB_DT_DEVICE:
890 ReadCachedDeviceDesc(pDev->pDescCache->pDevice, pbBuf, pcbBuf);
891 LogFlow(("vusbDevStdReqGetDescriptor: %s: %u bytes of device descriptors\n", pDev->pUsbIns->pszName, *pcbBuf));
892 return true;
893
894 case VUSB_DT_CONFIG:
895 {
896 unsigned int iIndex = (pSetup->wValue & 0xff);
897 if (iIndex >= pDev->pDescCache->pDevice->bNumConfigurations)
898 {
899 LogFlow(("vusbDevStdReqGetDescriptor: %s: iIndex=%u >= bNumConfigurations=%d !!!\n",
900 pDev->pUsbIns->pszName, iIndex, pDev->pDescCache->pDevice->bNumConfigurations));
901 return false;
902 }
903 ReadCachedConfigDesc(&pDev->pDescCache->paConfigs[iIndex], pbBuf, pcbBuf);
904 LogFlow(("vusbDevStdReqGetDescriptor: %s: %u bytes of config descriptors\n", pDev->pUsbIns->pszName, *pcbBuf));
905 return true;
906 }
907
908 case VUSB_DT_STRING:
909 {
910 if (pSetup->wIndex == 0)
911 {
912 ReadCachedLangIdDesc(pDev->pDescCache->paLanguages, pDev->pDescCache->cLanguages, pbBuf, pcbBuf);
913 LogFlow(("vusbDevStdReqGetDescriptor: %s: %u bytes of language ID (string) descriptors\n", pDev->pUsbIns->pszName, *pcbBuf));
914 return true;
915 }
916 PCPDMUSBDESCCACHESTRING pString;
917 pString = FindCachedString(pDev->pDescCache->paLanguages, pDev->pDescCache->cLanguages,
918 pSetup->wIndex, pSetup->wValue & 0xff);
919 if (pString)
920 {
921 ReadCachedStringDesc(pString, pbBuf, pcbBuf);
922 LogFlow(("vusbDevStdReqGetDescriptor: %s: %u bytes of string descriptors \"%s\"\n",
923 pDev->pUsbIns->pszName, *pcbBuf, pString->psz));
924 return true;
925 }
926 break;
927 }
928
929 default:
930 break;
931 }
932 }
933 Log(("vusb: %s: warning: unknown descriptor: type=%u descidx=%u lang=%u len=%u!!!\n",
934 pDev->pUsbIns->pszName, pSetup->wValue >> 8, pSetup->wValue & 0xff, pSetup->wIndex, pSetup->wLength));
935 return false;
936}
937
938
939/**
940 * Service the standard USB requests.
941 *
942 * Devices may call this from controlmsg() if you want vusb core to handle your standard
943 * request, it's not necessary - you could handle them manually
944 *
945 * @param pDev The device.
946 * @param EndPoint The endpoint.
947 * @param pSetup Pointer to the setup request structure.
948 * @param pvBuf Buffer?
949 * @param pcbBuf ?
950 */
951bool vusbDevStandardRequest(PVUSBDEV pDev, int EndPoint, PVUSBSETUP pSetup, void *pvBuf, uint32_t *pcbBuf)
952{
953 static bool (* const s_apfnStdReq[VUSB_REQ_MAX])(PVUSBDEV, int, PVUSBSETUP, uint8_t *, uint32_t *) =
954 {
955 vusbDevStdReqGetStatus,
956 vusbDevStdReqClearFeature,
957 NULL,
958 vusbDevStdReqSetFeature,
959 NULL,
960 vusbDevStdReqSetAddress,
961 vusbDevStdReqGetDescriptor,
962 NULL,
963 vusbDevStdReqGetConfig,
964 vusbDevStdReqSetConfig,
965 vusbDevStdReqGetInterface,
966 vusbDevStdReqSetInterface,
967 NULL /* for iso */
968 };
969
970 /*
971 * Check that the device is in a valid state.
972 */
973 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
974 if (enmState == VUSB_DEVICE_STATE_RESET)
975 {
976 LogRel(("VUSB: %s: standard control message ignored, the device is resetting\n", pDev->pUsbIns->pszName));
977 return false;
978 }
979
980 /*
981 * Do the request if it's one we want to deal with.
982 */
983 if ( pSetup->bRequest >= VUSB_REQ_MAX
984 || !s_apfnStdReq[pSetup->bRequest])
985 {
986 Log(("vusb: warning: standard req not implemented: message %u: val=%u idx=%u len=%u !!!\n",
987 pSetup->bRequest, pSetup->wValue, pSetup->wIndex, pSetup->wLength));
988 return false;
989 }
990
991 return s_apfnStdReq[pSetup->bRequest](pDev, EndPoint, pSetup, (uint8_t *)pvBuf, pcbBuf);
992}
993
994
995/**
996 * Sets the address of a device.
997 *
998 * Called by status_completion() and vusbDevResetWorker().
999 */
1000void vusbDevSetAddress(PVUSBDEV pDev, uint8_t u8Address)
1001{
1002 LogFlow(("vusbDevSetAddress: pDev=%p[%s]/%i u8Address=%#x\n",
1003 pDev, pDev->pUsbIns->pszName, pDev->i16Port, u8Address));
1004
1005 /*
1006 * Check that the device is in a valid state.
1007 */
1008 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
1009 VUSBDEV_ASSERT_VALID_STATE(enmState);
1010 if ( enmState == VUSB_DEVICE_STATE_ATTACHED
1011 || enmState == VUSB_DEVICE_STATE_DETACHED)
1012 {
1013 LogFlow(("vusbDevSetAddress: %s: fails because %d < POWERED\n", pDev->pUsbIns->pszName, pDev->enmState));
1014 return;
1015 }
1016 if (enmState == VUSB_DEVICE_STATE_RESET)
1017 {
1018 LogRel(("VUSB: %s: set address ignored, the device is resetting\n", pDev->pUsbIns->pszName));
1019 return;
1020 }
1021
1022 /*
1023 * Ok, get on with it.
1024 */
1025 if (pDev->u8Address == u8Address)
1026 return;
1027
1028 /** @todo The following logic belongs to the roothub and should actually be in that file. */
1029 PVUSBROOTHUB pRh = vusbDevGetRh(pDev);
1030 AssertPtrReturnVoid(pRh);
1031
1032 RTCritSectEnter(&pRh->CritSectDevices);
1033
1034 /* Remove the device from the current address. */
1035 if (pDev->u8Address != VUSB_INVALID_ADDRESS)
1036 {
1037 Assert(pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS] == pDev);
1038 pRh->apDevByAddr[pDev->u8Address] = NULL;
1039 }
1040
1041 if (u8Address == VUSB_DEFAULT_ADDRESS)
1042 {
1043 PVUSBDEV pDevDef = pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS];
1044
1045 if (pDevDef)
1046 {
1047 pDevDef->u8Address = VUSB_INVALID_ADDRESS;
1048 pDevDef->u8NewAddress = VUSB_INVALID_ADDRESS;
1049 vusbDevSetStateCmp(pDevDef, VUSB_DEVICE_STATE_POWERED, VUSB_DEVICE_STATE_DEFAULT);
1050 Log(("2 DEFAULT ADDRS\n"));
1051 }
1052
1053 pRh->apDevByAddr[VUSB_DEFAULT_ADDRESS] = pDev;
1054 vusbDevSetState(pDev, VUSB_DEVICE_STATE_DEFAULT);
1055 }
1056 else
1057 {
1058 Assert(!pRh->apDevByAddr[u8Address]);
1059 pRh->apDevByAddr[u8Address] = pDev;
1060 vusbDevSetState(pDev, VUSB_DEVICE_STATE_ADDRESS);
1061 }
1062
1063 pDev->u8Address = u8Address;
1064 RTCritSectLeave(&pRh->CritSectDevices);
1065
1066 Log(("vusb: %p[%s]/%i: Assigned address %u\n",
1067 pDev, pDev->pUsbIns->pszName, pDev->i16Port, u8Address));
1068}
1069
1070
1071static DECLCALLBACK(int) vusbDevCancelAllUrbsWorker(PVUSBDEV pDev, bool fDetaching)
1072{
1073 /*
1074 * Iterate the URBs and cancel them.
1075 */
1076 PVUSBURBVUSB pVUsbUrb, pVUsbUrbNext;
1077 RTListForEachSafe(&pDev->LstAsyncUrbs, pVUsbUrb, pVUsbUrbNext, VUSBURBVUSBINT, NdLst)
1078 {
1079 PVUSBURB pUrb = pVUsbUrb->pUrb;
1080
1081 Assert(pUrb->pVUsb->pDev == pDev);
1082
1083 LogFlow(("%s: vusbDevCancelAllUrbs: CANCELING URB\n", pUrb->pszDesc));
1084 int rc = vusbUrbCancelWorker(pUrb, CANCELMODE_FAIL);
1085 AssertRC(rc);
1086 }
1087
1088 /*
1089 * Reap any URBs which became ripe during cancel now.
1090 */
1091 RTCritSectEnter(&pDev->CritSectAsyncUrbs);
1092 unsigned cReaped;
1093 do
1094 {
1095 cReaped = 0;
1096 pVUsbUrb = RTListGetFirst(&pDev->LstAsyncUrbs, VUSBURBVUSBINT, NdLst);
1097 while (pVUsbUrb)
1098 {
1099 PVUSBURBVUSB pNext = RTListGetNext(&pDev->LstAsyncUrbs, pVUsbUrb, VUSBURBVUSBINT, NdLst);
1100 PVUSBURB pUrb = pVUsbUrb->pUrb;
1101 Assert(pUrb->pVUsb->pDev == pDev);
1102
1103 PVUSBURB pRipe = NULL;
1104 if (pUrb->enmState == VUSBURBSTATE_REAPED)
1105 pRipe = pUrb;
1106 else if (pUrb->enmState == VUSBURBSTATE_CANCELLED)
1107#ifdef RT_OS_WINDOWS /** @todo Windows doesn't do cancelling, thus this kludge to prevent really bad
1108 * things from happening if we leave a pending URB behinds. */
1109 pRipe = pDev->pUsbIns->pReg->pfnUrbReap(pDev->pUsbIns, fDetaching ? 1500 : 0 /*ms*/);
1110#else
1111 pRipe = pDev->pUsbIns->pReg->pfnUrbReap(pDev->pUsbIns, fDetaching ? 10 : 0 /*ms*/);
1112#endif
1113 else
1114 AssertMsgFailed(("pUrb=%p enmState=%d\n", pUrb, pUrb->enmState));
1115 if (pRipe)
1116 {
1117 if ( pNext
1118 && pRipe == pNext->pUrb)
1119 pNext = RTListGetNext(&pDev->LstAsyncUrbs, pNext, VUSBURBVUSBINT, NdLst);
1120 vusbUrbRipe(pRipe);
1121 cReaped++;
1122 }
1123
1124 pVUsbUrb = pNext;
1125 }
1126 } while (cReaped > 0);
1127
1128 /*
1129 * If we're detaching, we'll have to orphan any leftover URBs.
1130 */
1131 if (fDetaching)
1132 {
1133 RTListForEachSafe(&pDev->LstAsyncUrbs, pVUsbUrb, pVUsbUrbNext, VUSBURBVUSBINT, NdLst)
1134 {
1135 PVUSBURB pUrb = pVUsbUrb->pUrb;
1136 Assert(pUrb->pVUsb->pDev == pDev);
1137
1138 AssertMsgFailed(("%s: Leaking left over URB! state=%d pDev=%p[%s]\n",
1139 pUrb->pszDesc, pUrb->enmState, pDev, pDev->pUsbIns->pszName));
1140 vusbUrbUnlink(pUrb);
1141 /* Unlink isn't enough, because boundary timer and detaching will try to reap it.
1142 * It was tested with MSD & iphone attachment to vSMP guest, if
1143 * it breaks anything, please add comment here, why we should unlink only.
1144 */
1145 pUrb->pVUsb->pfnFree(pUrb);
1146 }
1147 }
1148 RTCritSectLeave(&pDev->CritSectAsyncUrbs);
1149 return VINF_SUCCESS;
1150}
1151
1152/**
1153 * Cancels and completes (with CRC failure) all async URBs pending
1154 * on a device. This is typically done as part of a reset and
1155 * before detaching a device.
1156 *
1157 * @returns nothing.
1158 * @param pDev The VUSB device instance.
1159 * @param fDetaching If set, we will unconditionally unlink (and leak)
1160 * any URBs which isn't reaped.
1161 */
1162DECLHIDDEN(void) vusbDevCancelAllUrbs(PVUSBDEV pDev, bool fDetaching)
1163{
1164 int rc = vusbDevIoThreadExecSync(pDev, (PFNRT)vusbDevCancelAllUrbsWorker, 2, pDev, fDetaching);
1165 AssertRC(rc);
1166}
1167
1168
1169static DECLCALLBACK(int) vusbDevUrbIoThread(RTTHREAD hThread, void *pvUser)
1170{
1171 PVUSBDEV pDev = (PVUSBDEV)pvUser;
1172
1173 /* Notify the starter that we are up and running. */
1174 RTThreadUserSignal(hThread);
1175
1176 LogFlowFunc(("Entering work loop\n"));
1177
1178 while (!ASMAtomicReadBool(&pDev->fTerminate))
1179 {
1180 if (vusbDevGetState(pDev) != VUSB_DEVICE_STATE_RESET)
1181 vusbUrbDoReapAsyncDev(pDev, RT_INDEFINITE_WAIT);
1182
1183 /* Process any URBs waiting to be cancelled first. */
1184 int rc = RTReqQueueProcess(pDev->hReqQueueSync, 0); /* Don't wait if there is nothing to do. */
1185 Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT); NOREF(rc);
1186 }
1187
1188 return VINF_SUCCESS;
1189}
1190
1191int vusbDevUrbIoThreadWakeup(PVUSBDEV pDev)
1192{
1193 ASMAtomicXchgBool(&pDev->fWokenUp, true);
1194 return pDev->pUsbIns->pReg->pfnWakeup(pDev->pUsbIns);
1195}
1196
1197/**
1198 * Create the URB I/O thread.
1199 *
1200 * @returns VBox status code.
1201 * @param pDev The VUSB device.
1202 */
1203int vusbDevUrbIoThreadCreate(PVUSBDEV pDev)
1204{
1205 int rc = VINF_SUCCESS;
1206
1207 ASMAtomicXchgBool(&pDev->fTerminate, false);
1208 rc = RTThreadCreateF(&pDev->hUrbIoThread, vusbDevUrbIoThread, pDev, 0, RTTHREADTYPE_IO,
1209 RTTHREADFLAGS_WAITABLE, "USBDevIo-%d", pDev->i16Port);
1210 if (RT_SUCCESS(rc))
1211 {
1212 /* Wait for it to become active. */
1213 rc = RTThreadUserWait(pDev->hUrbIoThread, RT_INDEFINITE_WAIT);
1214 }
1215
1216 return rc;
1217}
1218
1219/**
1220 * Destro the URB I/O thread.
1221 *
1222 * @returns VBox status code.
1223 * @param pDev The VUSB device.
1224 */
1225int vusbDevUrbIoThreadDestroy(PVUSBDEV pDev)
1226{
1227 int rc = VINF_SUCCESS;
1228 int rcThread = VINF_SUCCESS;
1229
1230 ASMAtomicXchgBool(&pDev->fTerminate, true);
1231 vusbDevUrbIoThreadWakeup(pDev);
1232
1233 rc = RTThreadWait(pDev->hUrbIoThread, RT_INDEFINITE_WAIT, &rcThread);
1234 if (RT_SUCCESS(rc))
1235 rc = rcThread;
1236
1237 pDev->hUrbIoThread = NIL_RTTHREAD;
1238
1239 return rc;
1240}
1241
1242
1243/**
1244 * Attaches a device to the given hub.
1245 *
1246 * @returns VBox status code.
1247 * @param pDev The device to attach.
1248 * @param pHub THe hub to attach to.
1249 */
1250int vusbDevAttach(PVUSBDEV pDev, PVUSBHUB pHub)
1251{
1252 AssertMsg(pDev->enmState == VUSB_DEVICE_STATE_DETACHED, ("enmState=%d\n", pDev->enmState));
1253
1254 pDev->pHub = pHub;
1255 pDev->enmState = VUSB_DEVICE_STATE_ATTACHED;
1256
1257 /* noone else ever messes with the default pipe while we are attached */
1258 vusbDevMapEndpoint(pDev, &g_Endpoint0);
1259 vusbDevDoSelectConfig(pDev, &g_Config0);
1260
1261 /* Create I/O thread and attach to the hub. */
1262 int rc = vusbDevUrbIoThreadCreate(pDev);
1263 if (RT_FAILURE(rc))
1264 {
1265 pDev->pHub = NULL;
1266 pDev->enmState = VUSB_DEVICE_STATE_DETACHED;
1267 }
1268
1269 return rc;
1270}
1271
1272
1273/**
1274 * Detaches a device from the hub it's attached to.
1275 *
1276 * @returns VBox status code.
1277 * @param pDev The device to detach.
1278 *
1279 * @remark This can be called in any state but reset.
1280 */
1281int vusbDevDetach(PVUSBDEV pDev)
1282{
1283 LogFlow(("vusbDevDetach: pDev=%p[%s] enmState=%#x\n", pDev, pDev->pUsbIns->pszName, pDev->enmState));
1284 VUSBDEV_ASSERT_VALID_STATE(pDev->enmState);
1285 Assert(pDev->enmState != VUSB_DEVICE_STATE_RESET);
1286
1287 /*
1288 * Destroy I/O thread and request queue last because they might still be used
1289 * when cancelling URBs.
1290 */
1291 vusbDevUrbIoThreadDestroy(pDev);
1292
1293 vusbDevSetState(pDev, VUSB_DEVICE_STATE_DETACHED);
1294 pDev->pHub = NULL;
1295
1296 /* Remove the configuration */
1297 pDev->pCurCfgDesc = NULL;
1298 for (unsigned i = 0; i < RT_ELEMENTS(pDev->aPipes); i++)
1299 vusbDevResetPipeData(&pDev->aPipes[i]);
1300 return VINF_SUCCESS;
1301}
1302
1303
1304/**
1305 * Destroys a device, detaching it from the hub if necessary.
1306 *
1307 * @param pDev The device.
1308 * @thread any.
1309 */
1310void vusbDevDestroy(PVUSBDEV pDev)
1311{
1312 LogFlow(("vusbDevDestroy: pDev=%p[%s] enmState=%d\n", pDev, pDev->pUsbIns->pszName, pDev->enmState));
1313
1314 RTMemFree(pDev->paIfStates);
1315
1316 PDMUsbHlpTimerDestroy(pDev->pUsbIns, pDev->hResetTimer);
1317 pDev->hResetTimer = NIL_TMTIMERHANDLE;
1318
1319 for (unsigned i = 0; i < RT_ELEMENTS(pDev->aPipes); i++)
1320 {
1321 Assert(pDev->aPipes[i].pCtrl == NULL);
1322 RTCritSectDelete(&pDev->aPipes[i].CritSectCtrl);
1323 }
1324
1325 if (pDev->hSniffer != VUSBSNIFFER_NIL)
1326 VUSBSnifferDestroy(pDev->hSniffer);
1327
1328 vusbUrbPoolDestroy(&pDev->UrbPool);
1329
1330 int rc = RTReqQueueDestroy(pDev->hReqQueueSync);
1331 AssertRC(rc);
1332 pDev->hReqQueueSync = NIL_RTREQQUEUE;
1333
1334 RTCritSectDelete(&pDev->CritSectAsyncUrbs);
1335 /* Not using vusbDevSetState() deliberately here because it would assert on the state. */
1336 pDev->enmState = VUSB_DEVICE_STATE_DESTROYED;
1337 pDev->pUsbIns->pvVUsbDev2 = NULL;
1338 RTMemFree(pDev);
1339}
1340
1341
1342/* -=-=-=-=-=- VUSBIDEVICE methods -=-=-=-=-=- */
1343
1344
1345/**
1346 * The actual reset has been done, do completion on EMT.
1347 *
1348 * There are several things we have to do now, like set default
1349 * config and address, and cleanup the state of control pipes.
1350 *
1351 * It's possible that the device has a delayed destroy request
1352 * pending when we get here. This can happen for async resetting.
1353 * We deal with it here, since we're now executing on the EMT
1354 * thread and the destruction will be properly serialized now.
1355 *
1356 * @param pDev The device that is being reset.
1357 * @param rc The vusbDevResetWorker return code.
1358 * @param pfnDone The done callback specified by the caller of vusbDevReset().
1359 * @param pvUser The user argument for the callback.
1360 */
1361static void vusbDevResetDone(PVUSBDEV pDev, int rc, PFNVUSBRESETDONE pfnDone, void *pvUser)
1362{
1363 VUSBDEV_ASSERT_VALID_STATE(pDev->enmState);
1364 Assert(pDev->enmState == VUSB_DEVICE_STATE_RESET);
1365
1366 /*
1367 * Do control pipe cleanup regardless of state and result.
1368 */
1369 for (unsigned i = 0; i < VUSB_PIPE_MAX; i++)
1370 if (pDev->aPipes[i].pCtrl)
1371 vusbMsgResetExtraData(pDev->aPipes[i].pCtrl);
1372
1373 /*
1374 * Switch to the default state.
1375 */
1376 vusbDevSetState(pDev, VUSB_DEVICE_STATE_DEFAULT);
1377 pDev->u16Status = 0;
1378 vusbDevDoSelectConfig(pDev, &g_Config0);
1379 if (!vusbDevIsRh(pDev))
1380 vusbDevSetAddress(pDev, VUSB_DEFAULT_ADDRESS);
1381 if (pfnDone)
1382 pfnDone(&pDev->IDevice, pDev->i16Port, rc, pvUser);
1383}
1384
1385
1386/**
1387 * @callback_method_impl{FNTMTIMERUSB,
1388 * Timer callback for doing reset completion.}
1389 */
1390static DECLCALLBACK(void) vusbDevResetDoneTimer(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, void *pvUser)
1391{
1392 PVUSBDEV pDev = (PVUSBDEV)pvUser;
1393 PVUSBRESETARGS pArgs = (PVUSBRESETARGS)pDev->pvArgs;
1394 Assert(pDev->pUsbIns == pUsbIns);
1395 RT_NOREF(pUsbIns, hTimer);
1396
1397 AssertPtr(pArgs);
1398
1399 /*
1400 * Reset-done processing and cleanup.
1401 */
1402 pDev->pvArgs = NULL;
1403 vusbDevResetDone(pDev, pArgs->rc, pArgs->pfnDone, pArgs->pvUser);
1404 RTMemFree(pArgs);
1405}
1406
1407
1408/**
1409 * Perform the actual reset.
1410 *
1411 * @thread EMT or a VUSB reset thread.
1412 */
1413static DECLCALLBACK(int) vusbDevResetWorker(PVUSBDEV pDev, bool fResetOnLinux, bool fUseTimer, PVUSBRESETARGS pArgs)
1414{
1415 uint64_t const uTimerDeadline = !fUseTimer ? 0
1416 : PDMUsbHlpTimerGet(pDev->pUsbIns, pDev->hResetTimer)
1417 + PDMUsbHlpTimerFromMilli(pDev->pUsbIns, pDev->hResetTimer, 10);
1418
1419 int rc = VINF_SUCCESS;
1420 if (pDev->pUsbIns->pReg->pfnUsbReset)
1421 rc = pDev->pUsbIns->pReg->pfnUsbReset(pDev->pUsbIns, fResetOnLinux);
1422
1423 if (pArgs)
1424 {
1425 pArgs->rc = rc;
1426 rc = VINF_SUCCESS;
1427 }
1428
1429 if (fUseTimer)
1430 {
1431 /*
1432 * We use a timer to communicate the result back to EMT.
1433 * This avoids suspend + poweroff issues, and it should give
1434 * us more accurate scheduling than making this thread sleep.
1435 */
1436 int rc2 = PDMUsbHlpTimerSet(pDev->pUsbIns, pDev->hResetTimer, uTimerDeadline);
1437 AssertReleaseRC(rc2);
1438 }
1439
1440 LogFlow(("vusbDevResetWorker: %s: returns %Rrc\n", pDev->pUsbIns->pszName, rc));
1441 return rc;
1442}
1443
1444
1445/**
1446 * Resets a device.
1447 *
1448 * Since a device reset shall take at least 10ms from the guest point of view,
1449 * it must be performed asynchronously. We create a thread which performs this
1450 * operation and ensures it will take at least 10ms.
1451 *
1452 * At times - like init - a synchronous reset is required, this can be done
1453 * by passing NULL for pfnDone.
1454 *
1455 * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state.
1456 * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful,
1457 * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed.
1458 *
1459 * @returns VBox status code.
1460 *
1461 * @param pDevice Pointer to the VUSB device interface.
1462 * @param fResetOnLinux Whether it's safe to reset the device(s) on a linux
1463 * host system. See discussion of logical reconnects elsewhere.
1464 * @param pfnDone Pointer to the completion routine. If NULL a synchronous
1465 * reset is preformed not respecting the 10ms.
1466 * @param pvUser Opaque user data to pass to the done callback.
1467 * @param pVM Pointer to the VM handle for performing the done function
1468 * on the EMT thread.
1469 * @thread EMT
1470 */
1471static DECLCALLBACK(int) vusbIDeviceReset(PVUSBIDEVICE pDevice, bool fResetOnLinux,
1472 PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM)
1473{
1474 RT_NOREF(pVM);
1475 PVUSBDEV pDev = (PVUSBDEV)pDevice;
1476 Assert(!pfnDone || pVM);
1477 LogFlow(("vusb: reset: [%s]/%i\n", pDev->pUsbIns->pszName, pDev->i16Port));
1478
1479 /*
1480 * Only one reset operation at a time.
1481 */
1482 const VUSBDEVICESTATE enmStateOld = vusbDevSetState(pDev, VUSB_DEVICE_STATE_RESET);
1483 if (enmStateOld == VUSB_DEVICE_STATE_RESET)
1484 {
1485 LogRel(("VUSB: %s: reset request is ignored, the device is already resetting!\n", pDev->pUsbIns->pszName));
1486 return VERR_VUSB_DEVICE_IS_RESETTING;
1487 }
1488
1489 /*
1490 * First, cancel all async URBs.
1491 */
1492 vusbDevCancelAllUrbs(pDev, false);
1493
1494 /* Async or sync? */
1495 if (pfnDone)
1496 {
1497 /*
1498 * Async fashion.
1499 */
1500 PVUSBRESETARGS pArgs = (PVUSBRESETARGS)RTMemTmpAlloc(sizeof(*pArgs));
1501 if (pArgs)
1502 {
1503 pArgs->pDev = pDev;
1504 pArgs->pfnDone = pfnDone;
1505 pArgs->pvUser = pvUser;
1506 pArgs->rc = VINF_SUCCESS;
1507 AssertPtrNull(pDev->pvArgs);
1508 pDev->pvArgs = pArgs;
1509 int rc = vusbDevIoThreadExec(pDev, 0 /* fFlags */, (PFNRT)vusbDevResetWorker, 4, pDev, fResetOnLinux, true, pArgs);
1510 if (RT_SUCCESS(rc))
1511 return rc;
1512
1513 RTMemTmpFree(pArgs);
1514 }
1515 /* fall back to sync on failure */
1516 }
1517
1518 /*
1519 * Sync fashion.
1520 */
1521 int rc = vusbDevResetWorker(pDev, fResetOnLinux, false, NULL);
1522 vusbDevResetDone(pDev, rc, pfnDone, pvUser);
1523 return rc;
1524}
1525
1526
1527/**
1528 * Powers on the device.
1529 *
1530 * @returns VBox status code.
1531 * @param pInterface Pointer to the device interface structure.
1532 */
1533static DECLCALLBACK(int) vusbIDevicePowerOn(PVUSBIDEVICE pInterface)
1534{
1535 PVUSBDEV pDev = (PVUSBDEV)pInterface;
1536 LogFlow(("vusbDevPowerOn: pDev=%p[%s]\n", pDev, pDev->pUsbIns->pszName));
1537
1538 /*
1539 * Check that the device is in a valid state.
1540 */
1541 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
1542 if (enmState == VUSB_DEVICE_STATE_DETACHED)
1543 {
1544 Log(("vusb: warning: attempt to power on detached device %p[%s]\n", pDev, pDev->pUsbIns->pszName));
1545 return VERR_VUSB_DEVICE_NOT_ATTACHED;
1546 }
1547 if (enmState == VUSB_DEVICE_STATE_RESET)
1548 {
1549 LogRel(("VUSB: %s: power on ignored, the device is resetting!\n", pDev->pUsbIns->pszName));
1550 return VERR_VUSB_DEVICE_IS_RESETTING;
1551 }
1552
1553 /*
1554 * Do the job.
1555 */
1556 if (enmState == VUSB_DEVICE_STATE_ATTACHED)
1557 vusbDevSetState(pDev, VUSB_DEVICE_STATE_POWERED);
1558
1559 return VINF_SUCCESS;
1560}
1561
1562
1563/**
1564 * Powers off the device.
1565 *
1566 * @returns VBox status code.
1567 * @param pInterface Pointer to the device interface structure.
1568 */
1569static DECLCALLBACK(int) vusbIDevicePowerOff(PVUSBIDEVICE pInterface)
1570{
1571 PVUSBDEV pDev = (PVUSBDEV)pInterface;
1572 LogFlow(("vusbDevPowerOff: pDev=%p[%s]\n", pDev, pDev->pUsbIns->pszName));
1573
1574 /*
1575 * Check that the device is in a valid state.
1576 */
1577 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
1578 if (enmState == VUSB_DEVICE_STATE_DETACHED)
1579 {
1580 Log(("vusb: warning: attempt to power off detached device %p[%s]\n", pDev, pDev->pUsbIns->pszName));
1581 return VERR_VUSB_DEVICE_NOT_ATTACHED;
1582 }
1583 if (enmState == VUSB_DEVICE_STATE_RESET)
1584 {
1585 LogRel(("VUSB: %s: power off ignored, the device is resetting!\n", pDev->pUsbIns->pszName));
1586 return VERR_VUSB_DEVICE_IS_RESETTING;
1587 }
1588
1589 /*
1590 * If it's a root hub, we will have to cancel all URBs and reap them.
1591 */
1592 if (vusbDevIsRh(pDev))
1593 {
1594 PVUSBROOTHUB pRh = (PVUSBROOTHUB)pDev;
1595 VUSBIRhCancelAllUrbs(&pRh->IRhConnector);
1596 VUSBIRhReapAsyncUrbs(&pRh->IRhConnector, pDev->i16Port, 0);
1597 }
1598
1599 vusbDevSetState(pDev, VUSB_DEVICE_STATE_ATTACHED);
1600 return VINF_SUCCESS;
1601}
1602
1603
1604/**
1605 * Get the state of the device.
1606 *
1607 * @returns Device state.
1608 * @param pInterface Pointer to the device interface structure.
1609 */
1610static DECLCALLBACK(VUSBDEVICESTATE) vusbIDeviceGetState(PVUSBIDEVICE pInterface)
1611{
1612 return vusbDevGetState((PVUSBDEV)pInterface);
1613}
1614
1615
1616/**
1617 * @interface_method_impl{VUSBIDEVICE,pfnIsSavedStateSupported}
1618 */
1619static DECLCALLBACK(bool) vusbIDeviceIsSavedStateSupported(PVUSBIDEVICE pInterface)
1620{
1621 PVUSBDEV pDev = (PVUSBDEV)pInterface;
1622 bool fSavedStateSupported = RT_BOOL(pDev->pUsbIns->pReg->fFlags & PDM_USBREG_SAVED_STATE_SUPPORTED);
1623
1624 LogFlowFunc(("pInterface=%p\n", pInterface));
1625
1626 LogFlowFunc(("returns %RTbool\n", fSavedStateSupported));
1627 return fSavedStateSupported;
1628}
1629
1630
1631/**
1632 * @interface_method_impl{VUSBIDEVICE,pfnGetState}
1633 */
1634static DECLCALLBACK(VUSBSPEED) vusbIDeviceGetSpeed(PVUSBIDEVICE pInterface)
1635{
1636 PVUSBDEV pDev = (PVUSBDEV)pInterface;
1637 VUSBSPEED enmSpeed = pDev->pUsbIns->enmSpeed;
1638
1639 LogFlowFunc(("pInterface=%p, returns %u\n", pInterface, enmSpeed));
1640 return enmSpeed;
1641}
1642
1643
1644/**
1645 * The maximum number of interfaces the device can have in all of it's configuration.
1646 *
1647 * @returns Number of interfaces.
1648 * @param pDev The device.
1649 */
1650size_t vusbDevMaxInterfaces(PVUSBDEV pDev)
1651{
1652 uint8_t cMax = 0;
1653 unsigned i = pDev->pDescCache->pDevice->bNumConfigurations;
1654 while (i-- > 0)
1655 {
1656 if (pDev->pDescCache->paConfigs[i].Core.bNumInterfaces > cMax)
1657 cMax = pDev->pDescCache->paConfigs[i].Core.bNumInterfaces;
1658 }
1659
1660 return cMax;
1661}
1662
1663
1664/**
1665 * Executes a given function on the I/O thread.
1666 *
1667 * @returns IPRT status code.
1668 * @param pDev The USB device instance data.
1669 * @param fFlags Combination of VUSB_DEV_IO_THREAD_EXEC_FLAGS_*
1670 * @param pfnFunction The function to execute.
1671 * @param cArgs Number of arguments to the function.
1672 * @param Args The parameter list.
1673 *
1674 * @remarks See remarks on RTReqQueueCallV
1675 */
1676DECLHIDDEN(int) vusbDevIoThreadExecV(PVUSBDEV pDev, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args)
1677{
1678 int rc = VINF_SUCCESS;
1679 PRTREQ hReq = NULL;
1680
1681 Assert(pDev->hUrbIoThread != NIL_RTTHREAD);
1682 if (RT_LIKELY(pDev->hUrbIoThread != NIL_RTTHREAD))
1683 {
1684 uint32_t fReqFlags = RTREQFLAGS_IPRT_STATUS;
1685
1686 if (!(fFlags & VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC))
1687 fReqFlags |= RTREQFLAGS_NO_WAIT;
1688
1689 rc = RTReqQueueCallV(pDev->hReqQueueSync, &hReq, 0 /* cMillies */, fReqFlags, pfnFunction, cArgs, Args);
1690 Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
1691
1692 /* In case we are called on the I/O thread just process the request. */
1693 if ( pDev->hUrbIoThread == RTThreadSelf()
1694 && (fFlags & VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC))
1695 {
1696 int rc2 = RTReqQueueProcess(pDev->hReqQueueSync, 0);
1697 Assert(RT_SUCCESS(rc2) || rc2 == VERR_TIMEOUT); NOREF(rc2);
1698 }
1699 else
1700 vusbDevUrbIoThreadWakeup(pDev);
1701
1702 if ( rc == VERR_TIMEOUT
1703 && (fFlags & VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC))
1704 {
1705 rc = RTReqWait(hReq, RT_INDEFINITE_WAIT);
1706 AssertRC(rc);
1707 }
1708 RTReqRelease(hReq);
1709 }
1710 else
1711 rc = VERR_INVALID_STATE;
1712
1713 return rc;
1714}
1715
1716
1717/**
1718 * Executes a given function on the I/O thread.
1719 *
1720 * @returns IPRT status code.
1721 * @param pDev The USB device instance data.
1722 * @param fFlags Combination of VUSB_DEV_IO_THREAD_EXEC_FLAGS_*
1723 * @param pfnFunction The function to execute.
1724 * @param cArgs Number of arguments to the function.
1725 * @param ... The parameter list.
1726 *
1727 * @remarks See remarks on RTReqQueueCallV
1728 */
1729DECLHIDDEN(int) vusbDevIoThreadExec(PVUSBDEV pDev, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...)
1730{
1731 int rc = VINF_SUCCESS;
1732 va_list va;
1733
1734 va_start(va, cArgs);
1735 rc = vusbDevIoThreadExecV(pDev, fFlags, pfnFunction, cArgs, va);
1736 va_end(va);
1737 return rc;
1738}
1739
1740
1741/**
1742 * Executes a given function synchronously on the I/O thread waiting for it to complete.
1743 *
1744 * @returns IPRT status code.
1745 * @param pDev The USB device instance data
1746 * @param pfnFunction The function to execute.
1747 * @param cArgs Number of arguments to the function.
1748 * @param ... The parameter list.
1749 *
1750 * @remarks See remarks on RTReqQueueCallV
1751 */
1752DECLHIDDEN(int) vusbDevIoThreadExecSync(PVUSBDEV pDev, PFNRT pfnFunction, unsigned cArgs, ...)
1753{
1754 int rc = VINF_SUCCESS;
1755 va_list va;
1756
1757 va_start(va, cArgs);
1758 rc = vusbDevIoThreadExecV(pDev, VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC, pfnFunction, cArgs, va);
1759 va_end(va);
1760 return rc;
1761}
1762
1763
1764/**
1765 * Initialize a new VUSB device.
1766 *
1767 * @returns VBox status code.
1768 * @param pDev The VUSB device to initialize.
1769 * @param pUsbIns Pointer to the PDM USB Device instance.
1770 * @param pszCaptureFilename Optional fileame to capture the traffic to.
1771 */
1772int vusbDevInit(PVUSBDEV pDev, PPDMUSBINS pUsbIns, const char *pszCaptureFilename)
1773{
1774 /*
1775 * Initialize the device data members.
1776 * (All that are Non-Zero at least.)
1777 */
1778 Assert(!pDev->IDevice.pfnReset);
1779 Assert(!pDev->IDevice.pfnPowerOn);
1780 Assert(!pDev->IDevice.pfnPowerOff);
1781 Assert(!pDev->IDevice.pfnGetState);
1782 Assert(!pDev->IDevice.pfnIsSavedStateSupported);
1783
1784 pDev->IDevice.pfnReset = vusbIDeviceReset;
1785 pDev->IDevice.pfnPowerOn = vusbIDevicePowerOn;
1786 pDev->IDevice.pfnPowerOff = vusbIDevicePowerOff;
1787 pDev->IDevice.pfnGetState = vusbIDeviceGetState;
1788 pDev->IDevice.pfnIsSavedStateSupported = vusbIDeviceIsSavedStateSupported;
1789 pDev->IDevice.pfnGetSpeed = vusbIDeviceGetSpeed;
1790 pDev->pUsbIns = pUsbIns;
1791 pDev->pHub = NULL;
1792 pDev->enmState = VUSB_DEVICE_STATE_DETACHED;
1793 pDev->cRefs = 1;
1794 pDev->u8Address = VUSB_INVALID_ADDRESS;
1795 pDev->u8NewAddress = VUSB_INVALID_ADDRESS;
1796 pDev->i16Port = -1;
1797 pDev->u16Status = 0;
1798 pDev->pDescCache = NULL;
1799 pDev->pCurCfgDesc = NULL;
1800 pDev->paIfStates = NULL;
1801 RTListInit(&pDev->LstAsyncUrbs);
1802 memset(&pDev->aPipes[0], 0, sizeof(pDev->aPipes));
1803 for (unsigned i = 0; i < RT_ELEMENTS(pDev->aPipes); i++)
1804 {
1805 int rc = RTCritSectInit(&pDev->aPipes[i].CritSectCtrl);
1806 AssertRCReturn(rc, rc);
1807 }
1808 pDev->hResetTimer = NIL_TMTIMERHANDLE;
1809 pDev->hSniffer = VUSBSNIFFER_NIL;
1810
1811 int rc = RTCritSectInit(&pDev->CritSectAsyncUrbs);
1812 AssertRCReturn(rc, rc);
1813
1814 /* Create the URB pool. */
1815 rc = vusbUrbPoolInit(&pDev->UrbPool);
1816 AssertRCReturn(rc, rc);
1817
1818 /* Setup request queue executing synchronous tasks on the I/O thread. */
1819 rc = RTReqQueueCreate(&pDev->hReqQueueSync);
1820 AssertRCReturn(rc, rc);
1821
1822 /*
1823 * Create the reset timer. Make sure the name is unique as we're generic code.
1824 */
1825 static uint32_t volatile s_iSeq;
1826 char szDesc[32];
1827 RTStrPrintf(szDesc, sizeof(szDesc), "VUSB Reset #%u", ASMAtomicIncU32(&s_iSeq));
1828 rc = PDMUsbHlpTimerCreate(pDev->pUsbIns, TMCLOCK_VIRTUAL, vusbDevResetDoneTimer, pDev, 0 /*fFlags*/,
1829 szDesc, &pDev->hResetTimer);
1830 AssertRCReturn(rc, rc);
1831
1832 if (pszCaptureFilename)
1833 {
1834 rc = VUSBSnifferCreate(&pDev->hSniffer, 0, pszCaptureFilename, NULL, NULL);
1835 AssertRCReturn(rc, rc);
1836 }
1837
1838 /*
1839 * Get the descriptor cache from the device. (shall cannot fail)
1840 */
1841 pDev->pDescCache = pUsbIns->pReg->pfnUsbGetDescriptorCache(pUsbIns);
1842 AssertPtr(pDev->pDescCache);
1843#ifdef VBOX_STRICT
1844 if (pDev->pDescCache->fUseCachedStringsDescriptors)
1845 {
1846 int32_t iPrevId = -1;
1847 for (unsigned iLang = 0; iLang < pDev->pDescCache->cLanguages; iLang++)
1848 {
1849 Assert((int32_t)pDev->pDescCache->paLanguages[iLang].idLang > iPrevId);
1850 iPrevId = pDev->pDescCache->paLanguages[iLang].idLang;
1851
1852 int32_t idxPrevStr = -1;
1853 PCPDMUSBDESCCACHESTRING paStrings = pDev->pDescCache->paLanguages[iLang].paStrings;
1854 unsigned cStrings = pDev->pDescCache->paLanguages[iLang].cStrings;
1855 for (unsigned iStr = 0; iStr < cStrings; iStr++)
1856 {
1857 Assert((int32_t)paStrings[iStr].idx > idxPrevStr);
1858 idxPrevStr = paStrings[iStr].idx;
1859 size_t cch = strlen(paStrings[iStr].psz);
1860 Assert(cch <= 127);
1861 }
1862 }
1863 }
1864#endif
1865
1866 /*
1867 * Allocate memory for the interface states.
1868 */
1869 size_t cbIface = vusbDevMaxInterfaces(pDev) * sizeof(*pDev->paIfStates);
1870 pDev->paIfStates = (PVUSBINTERFACESTATE)RTMemAllocZ(cbIface);
1871 AssertMsgReturn(pDev->paIfStates, ("RTMemAllocZ(%d) failed\n", cbIface), VERR_NO_MEMORY);
1872
1873 return VINF_SUCCESS;
1874}
1875
1876/*
1877 * Local Variables:
1878 * mode: c
1879 * c-file-style: "bsd"
1880 * c-basic-offset: 4
1881 * tab-width: 4
1882 * indent-tabs-mode: s
1883 * End:
1884 */
1885
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette