VirtualBox

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

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

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

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 63.7 KB
 
1/* $Id: VUSBDevice.cpp 93914 2022-02-24 12:20:43Z 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 * Add a device to the address hash
997 */
998static void vusbDevAddressHash(PVUSBDEV pDev)
999{
1000 if (pDev->u8Address == VUSB_INVALID_ADDRESS)
1001 return;
1002 uint8_t u8Hash = vusbHashAddress(pDev->u8Address);
1003 pDev->pNextHash = pDev->pHub->pRootHub->apAddrHash[u8Hash];
1004 pDev->pHub->pRootHub->apAddrHash[u8Hash] = pDev;
1005}
1006
1007/**
1008 * Remove a device from the address hash
1009 */
1010static void vusbDevAddressUnHash(PVUSBDEV pDev)
1011{
1012 if (pDev->u8Address == VUSB_INVALID_ADDRESS)
1013 return;
1014
1015 uint8_t u8Hash = vusbHashAddress(pDev->u8Address);
1016 pDev->u8Address = VUSB_INVALID_ADDRESS;
1017 pDev->u8NewAddress = VUSB_INVALID_ADDRESS;
1018
1019 RTCritSectEnter(&pDev->pHub->pRootHub->CritSectDevices);
1020 PVUSBDEV pCur = pDev->pHub->pRootHub->apAddrHash[u8Hash];
1021 if (pCur == pDev)
1022 {
1023 /* special case, we're at the head */
1024 pDev->pHub->pRootHub->apAddrHash[u8Hash] = pDev->pNextHash;
1025 pDev->pNextHash = NULL;
1026 }
1027 else
1028 {
1029 /* search the list */
1030 PVUSBDEV pPrev;
1031 for (pPrev = pCur, pCur = pCur->pNextHash;
1032 pCur;
1033 pPrev = pCur, pCur = pCur->pNextHash)
1034 {
1035 if (pCur == pDev)
1036 {
1037 pPrev->pNextHash = pCur->pNextHash;
1038 pDev->pNextHash = NULL;
1039 break;
1040 }
1041 }
1042 }
1043 RTCritSectLeave(&pDev->pHub->pRootHub->CritSectDevices);
1044}
1045
1046/**
1047 * Sets the address of a device.
1048 *
1049 * Called by status_completion() and vusbDevResetWorker().
1050 */
1051void vusbDevSetAddress(PVUSBDEV pDev, uint8_t u8Address)
1052{
1053 LogFlow(("vusbDevSetAddress: pDev=%p[%s]/%i u8Address=%#x\n",
1054 pDev, pDev->pUsbIns->pszName, pDev->i16Port, u8Address));
1055
1056 /*
1057 * Check that the device is in a valid state.
1058 */
1059 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
1060 VUSBDEV_ASSERT_VALID_STATE(enmState);
1061 if ( enmState == VUSB_DEVICE_STATE_ATTACHED
1062 || enmState == VUSB_DEVICE_STATE_DETACHED)
1063 {
1064 LogFlow(("vusbDevSetAddress: %s: fails because %d < POWERED\n", pDev->pUsbIns->pszName, pDev->enmState));
1065 return;
1066 }
1067 if (enmState == VUSB_DEVICE_STATE_RESET)
1068 {
1069 LogRel(("VUSB: %s: set address ignored, the device is resetting\n", pDev->pUsbIns->pszName));
1070 return;
1071 }
1072
1073 /*
1074 * Ok, get on with it.
1075 */
1076 if (pDev->u8Address == u8Address)
1077 return;
1078
1079 PVUSBROOTHUB pRh = vusbDevGetRh(pDev);
1080 AssertPtrReturnVoid(pRh);
1081 if (pDev->u8Address == VUSB_DEFAULT_ADDRESS)
1082 pRh->pDefaultAddress = NULL;
1083
1084 vusbDevAddressUnHash(pDev);
1085
1086 if (u8Address == VUSB_DEFAULT_ADDRESS)
1087 {
1088 if (pRh->pDefaultAddress != NULL)
1089 {
1090 vusbDevAddressUnHash(pRh->pDefaultAddress);
1091 vusbDevSetStateCmp(pRh->pDefaultAddress, VUSB_DEVICE_STATE_POWERED, VUSB_DEVICE_STATE_DEFAULT);
1092 Log(("2 DEFAULT ADDRS\n"));
1093 }
1094
1095 pRh->pDefaultAddress = pDev;
1096 vusbDevSetState(pDev, VUSB_DEVICE_STATE_DEFAULT);
1097 }
1098 else
1099 vusbDevSetState(pDev, VUSB_DEVICE_STATE_ADDRESS);
1100
1101 pDev->u8Address = u8Address;
1102 vusbDevAddressHash(pDev);
1103
1104 Log(("vusb: %p[%s]/%i: Assigned address %u\n",
1105 pDev, pDev->pUsbIns->pszName, pDev->i16Port, u8Address));
1106}
1107
1108
1109static DECLCALLBACK(int) vusbDevCancelAllUrbsWorker(PVUSBDEV pDev, bool fDetaching)
1110{
1111 /*
1112 * Iterate the URBs and cancel them.
1113 */
1114 PVUSBURBVUSB pVUsbUrb, pVUsbUrbNext;
1115 RTListForEachSafe(&pDev->LstAsyncUrbs, pVUsbUrb, pVUsbUrbNext, VUSBURBVUSBINT, NdLst)
1116 {
1117 PVUSBURB pUrb = pVUsbUrb->pUrb;
1118
1119 Assert(pUrb->pVUsb->pDev == pDev);
1120
1121 LogFlow(("%s: vusbDevCancelAllUrbs: CANCELING URB\n", pUrb->pszDesc));
1122 int rc = vusbUrbCancelWorker(pUrb, CANCELMODE_FAIL);
1123 AssertRC(rc);
1124 }
1125
1126 /*
1127 * Reap any URBs which became ripe during cancel now.
1128 */
1129 RTCritSectEnter(&pDev->CritSectAsyncUrbs);
1130 unsigned cReaped;
1131 do
1132 {
1133 cReaped = 0;
1134 pVUsbUrb = RTListGetFirst(&pDev->LstAsyncUrbs, VUSBURBVUSBINT, NdLst);
1135 while (pVUsbUrb)
1136 {
1137 PVUSBURBVUSB pNext = RTListGetNext(&pDev->LstAsyncUrbs, pVUsbUrb, VUSBURBVUSBINT, NdLst);
1138 PVUSBURB pUrb = pVUsbUrb->pUrb;
1139 Assert(pUrb->pVUsb->pDev == pDev);
1140
1141 PVUSBURB pRipe = NULL;
1142 if (pUrb->enmState == VUSBURBSTATE_REAPED)
1143 pRipe = pUrb;
1144 else if (pUrb->enmState == VUSBURBSTATE_CANCELLED)
1145#ifdef RT_OS_WINDOWS /** @todo Windows doesn't do cancelling, thus this kludge to prevent really bad
1146 * things from happening if we leave a pending URB behinds. */
1147 pRipe = pDev->pUsbIns->pReg->pfnUrbReap(pDev->pUsbIns, fDetaching ? 1500 : 0 /*ms*/);
1148#else
1149 pRipe = pDev->pUsbIns->pReg->pfnUrbReap(pDev->pUsbIns, fDetaching ? 10 : 0 /*ms*/);
1150#endif
1151 else
1152 AssertMsgFailed(("pUrb=%p enmState=%d\n", pUrb, pUrb->enmState));
1153 if (pRipe)
1154 {
1155 if ( pNext
1156 && pRipe == pNext->pUrb)
1157 pNext = RTListGetNext(&pDev->LstAsyncUrbs, pNext, VUSBURBVUSBINT, NdLst);
1158 vusbUrbRipe(pRipe);
1159 cReaped++;
1160 }
1161
1162 pVUsbUrb = pNext;
1163 }
1164 } while (cReaped > 0);
1165
1166 /*
1167 * If we're detaching, we'll have to orphan any leftover URBs.
1168 */
1169 if (fDetaching)
1170 {
1171 RTListForEachSafe(&pDev->LstAsyncUrbs, pVUsbUrb, pVUsbUrbNext, VUSBURBVUSBINT, NdLst)
1172 {
1173 PVUSBURB pUrb = pVUsbUrb->pUrb;
1174 Assert(pUrb->pVUsb->pDev == pDev);
1175
1176 AssertMsgFailed(("%s: Leaking left over URB! state=%d pDev=%p[%s]\n",
1177 pUrb->pszDesc, pUrb->enmState, pDev, pDev->pUsbIns->pszName));
1178 vusbUrbUnlink(pUrb);
1179 /* Unlink isn't enough, because boundary timer and detaching will try to reap it.
1180 * It was tested with MSD & iphone attachment to vSMP guest, if
1181 * it breaks anything, please add comment here, why we should unlink only.
1182 */
1183 pUrb->pVUsb->pfnFree(pUrb);
1184 }
1185 }
1186 RTCritSectLeave(&pDev->CritSectAsyncUrbs);
1187 return VINF_SUCCESS;
1188}
1189
1190/**
1191 * Cancels and completes (with CRC failure) all async URBs pending
1192 * on a device. This is typically done as part of a reset and
1193 * before detaching a device.
1194 *
1195 * @returns nothing.
1196 * @param pDev The VUSB device instance.
1197 * @param fDetaching If set, we will unconditionally unlink (and leak)
1198 * any URBs which isn't reaped.
1199 */
1200DECLHIDDEN(void) vusbDevCancelAllUrbs(PVUSBDEV pDev, bool fDetaching)
1201{
1202 int rc = vusbDevIoThreadExecSync(pDev, (PFNRT)vusbDevCancelAllUrbsWorker, 2, pDev, fDetaching);
1203 AssertRC(rc);
1204}
1205
1206
1207static DECLCALLBACK(int) vusbDevUrbIoThread(RTTHREAD hThread, void *pvUser)
1208{
1209 PVUSBDEV pDev = (PVUSBDEV)pvUser;
1210
1211 /* Notify the starter that we are up and running. */
1212 RTThreadUserSignal(hThread);
1213
1214 LogFlowFunc(("Entering work loop\n"));
1215
1216 while (!ASMAtomicReadBool(&pDev->fTerminate))
1217 {
1218 if (vusbDevGetState(pDev) != VUSB_DEVICE_STATE_RESET)
1219 vusbUrbDoReapAsyncDev(pDev, RT_INDEFINITE_WAIT);
1220
1221 /* Process any URBs waiting to be cancelled first. */
1222 int rc = RTReqQueueProcess(pDev->hReqQueueSync, 0); /* Don't wait if there is nothing to do. */
1223 Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT); NOREF(rc);
1224 }
1225
1226 return VINF_SUCCESS;
1227}
1228
1229int vusbDevUrbIoThreadWakeup(PVUSBDEV pDev)
1230{
1231 ASMAtomicXchgBool(&pDev->fWokenUp, true);
1232 return pDev->pUsbIns->pReg->pfnWakeup(pDev->pUsbIns);
1233}
1234
1235/**
1236 * Create the URB I/O thread.
1237 *
1238 * @returns VBox status code.
1239 * @param pDev The VUSB device.
1240 */
1241int vusbDevUrbIoThreadCreate(PVUSBDEV pDev)
1242{
1243 int rc = VINF_SUCCESS;
1244
1245 ASMAtomicXchgBool(&pDev->fTerminate, false);
1246 rc = RTThreadCreateF(&pDev->hUrbIoThread, vusbDevUrbIoThread, pDev, 0, RTTHREADTYPE_IO,
1247 RTTHREADFLAGS_WAITABLE, "USBDevIo-%d", pDev->i16Port);
1248 if (RT_SUCCESS(rc))
1249 {
1250 /* Wait for it to become active. */
1251 rc = RTThreadUserWait(pDev->hUrbIoThread, RT_INDEFINITE_WAIT);
1252 }
1253
1254 return rc;
1255}
1256
1257/**
1258 * Destro the URB I/O thread.
1259 *
1260 * @returns VBox status code.
1261 * @param pDev The VUSB device.
1262 */
1263int vusbDevUrbIoThreadDestroy(PVUSBDEV pDev)
1264{
1265 int rc = VINF_SUCCESS;
1266 int rcThread = VINF_SUCCESS;
1267
1268 ASMAtomicXchgBool(&pDev->fTerminate, true);
1269 vusbDevUrbIoThreadWakeup(pDev);
1270
1271 rc = RTThreadWait(pDev->hUrbIoThread, RT_INDEFINITE_WAIT, &rcThread);
1272 if (RT_SUCCESS(rc))
1273 rc = rcThread;
1274
1275 pDev->hUrbIoThread = NIL_RTTHREAD;
1276
1277 return rc;
1278}
1279
1280
1281/**
1282 * Attaches a device to the given hub.
1283 *
1284 * @returns VBox status code.
1285 * @param pDev The device to attach.
1286 * @param pHub THe hub to attach to.
1287 */
1288int vusbDevAttach(PVUSBDEV pDev, PVUSBHUB pHub)
1289{
1290 AssertMsg(pDev->enmState == VUSB_DEVICE_STATE_DETACHED, ("enmState=%d\n", pDev->enmState));
1291
1292 pDev->pHub = pHub;
1293 pDev->enmState = VUSB_DEVICE_STATE_ATTACHED;
1294
1295 /* noone else ever messes with the default pipe while we are attached */
1296 vusbDevMapEndpoint(pDev, &g_Endpoint0);
1297 vusbDevDoSelectConfig(pDev, &g_Config0);
1298
1299 /* Create I/O thread and attach to the hub. */
1300 int rc = vusbDevUrbIoThreadCreate(pDev);
1301 if (RT_SUCCESS(rc))
1302 rc = pHub->pOps->pfnAttach(pHub, pDev);
1303
1304 if (RT_FAILURE(rc))
1305 {
1306 pDev->pHub = NULL;
1307 pDev->enmState = VUSB_DEVICE_STATE_DETACHED;
1308 }
1309
1310 return rc;
1311}
1312
1313
1314/**
1315 * Detaches a device from the hub it's attached to.
1316 *
1317 * @returns VBox status code.
1318 * @param pDev The device to detach.
1319 *
1320 * @remark This can be called in any state but reset.
1321 */
1322int vusbDevDetach(PVUSBDEV pDev)
1323{
1324 LogFlow(("vusbDevDetach: pDev=%p[%s] enmState=%#x\n", pDev, pDev->pUsbIns->pszName, pDev->enmState));
1325 VUSBDEV_ASSERT_VALID_STATE(pDev->enmState);
1326 Assert(pDev->enmState != VUSB_DEVICE_STATE_RESET);
1327
1328 vusbDevCancelAllUrbs(pDev, true);
1329 vusbDevAddressUnHash(pDev);
1330
1331 PVUSBROOTHUB pRh = vusbDevGetRh(pDev);
1332 if (!pRh)
1333 AssertMsgFailedReturn(("Not attached!\n"), VERR_VUSB_DEVICE_NOT_ATTACHED);
1334 if (pRh->pDefaultAddress == pDev)
1335 pRh->pDefaultAddress = NULL;
1336
1337 pDev->pHub->pOps->pfnDetach(pDev->pHub, pDev);
1338 pDev->i16Port = -1;
1339
1340 /*
1341 * Destroy I/O thread and request queue last because they might still be used
1342 * when cancelling URBs.
1343 */
1344 vusbDevUrbIoThreadDestroy(pDev);
1345
1346 vusbDevSetState(pDev, VUSB_DEVICE_STATE_DETACHED);
1347 pDev->pHub = NULL;
1348
1349 /* Remove the configuration */
1350 pDev->pCurCfgDesc = NULL;
1351 for (unsigned i = 0; i < RT_ELEMENTS(pDev->aPipes); i++)
1352 vusbDevResetPipeData(&pDev->aPipes[i]);
1353 return VINF_SUCCESS;
1354}
1355
1356
1357/**
1358 * Destroys a device, detaching it from the hub if necessary.
1359 *
1360 * @param pDev The device.
1361 * @thread any.
1362 */
1363void vusbDevDestroy(PVUSBDEV pDev)
1364{
1365 LogFlow(("vusbDevDestroy: pDev=%p[%s] enmState=%d\n", pDev, pDev->pUsbIns->pszName, pDev->enmState));
1366
1367 RTMemFree(pDev->paIfStates);
1368
1369 PDMUsbHlpTimerDestroy(pDev->pUsbIns, pDev->hResetTimer);
1370 pDev->hResetTimer = NIL_TMTIMERHANDLE;
1371
1372 for (unsigned i = 0; i < RT_ELEMENTS(pDev->aPipes); i++)
1373 {
1374 Assert(pDev->aPipes[i].pCtrl == NULL);
1375 RTCritSectDelete(&pDev->aPipes[i].CritSectCtrl);
1376 }
1377
1378 if (pDev->hSniffer != VUSBSNIFFER_NIL)
1379 VUSBSnifferDestroy(pDev->hSniffer);
1380
1381 vusbUrbPoolDestroy(&pDev->UrbPool);
1382
1383 int rc = RTReqQueueDestroy(pDev->hReqQueueSync);
1384 AssertRC(rc);
1385 pDev->hReqQueueSync = NIL_RTREQQUEUE;
1386
1387 RTCritSectDelete(&pDev->CritSectAsyncUrbs);
1388 /* Not using vusbDevSetState() deliberately here because it would assert on the state. */
1389 pDev->enmState = VUSB_DEVICE_STATE_DESTROYED;
1390 pDev->pUsbIns->pvVUsbDev2 = NULL;
1391 RTMemFree(pDev);
1392}
1393
1394
1395/* -=-=-=-=-=- VUSBIDEVICE methods -=-=-=-=-=- */
1396
1397
1398/**
1399 * The actual reset has been done, do completion on EMT.
1400 *
1401 * There are several things we have to do now, like set default
1402 * config and address, and cleanup the state of control pipes.
1403 *
1404 * It's possible that the device has a delayed destroy request
1405 * pending when we get here. This can happen for async resetting.
1406 * We deal with it here, since we're now executing on the EMT
1407 * thread and the destruction will be properly serialized now.
1408 *
1409 * @param pDev The device that is being reset.
1410 * @param rc The vusbDevResetWorker return code.
1411 * @param pfnDone The done callback specified by the caller of vusbDevReset().
1412 * @param pvUser The user argument for the callback.
1413 */
1414static void vusbDevResetDone(PVUSBDEV pDev, int rc, PFNVUSBRESETDONE pfnDone, void *pvUser)
1415{
1416 VUSBDEV_ASSERT_VALID_STATE(pDev->enmState);
1417 Assert(pDev->enmState == VUSB_DEVICE_STATE_RESET);
1418
1419 /*
1420 * Do control pipe cleanup regardless of state and result.
1421 */
1422 for (unsigned i = 0; i < VUSB_PIPE_MAX; i++)
1423 if (pDev->aPipes[i].pCtrl)
1424 vusbMsgResetExtraData(pDev->aPipes[i].pCtrl);
1425
1426 /*
1427 * Switch to the default state.
1428 */
1429 vusbDevSetState(pDev, VUSB_DEVICE_STATE_DEFAULT);
1430 pDev->u16Status = 0;
1431 vusbDevDoSelectConfig(pDev, &g_Config0);
1432 if (!vusbDevIsRh(pDev))
1433 vusbDevSetAddress(pDev, VUSB_DEFAULT_ADDRESS);
1434 if (pfnDone)
1435 pfnDone(&pDev->IDevice, pDev->i16Port, rc, pvUser);
1436}
1437
1438
1439/**
1440 * @callback_method_impl{FNTMTIMERUSB,
1441 * Timer callback for doing reset completion.}
1442 */
1443static DECLCALLBACK(void) vusbDevResetDoneTimer(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer, void *pvUser)
1444{
1445 PVUSBDEV pDev = (PVUSBDEV)pvUser;
1446 PVUSBRESETARGS pArgs = (PVUSBRESETARGS)pDev->pvArgs;
1447 Assert(pDev->pUsbIns == pUsbIns);
1448 RT_NOREF(pUsbIns, hTimer);
1449
1450 AssertPtr(pArgs);
1451
1452 /*
1453 * Reset-done processing and cleanup.
1454 */
1455 pDev->pvArgs = NULL;
1456 vusbDevResetDone(pDev, pArgs->rc, pArgs->pfnDone, pArgs->pvUser);
1457 RTMemFree(pArgs);
1458}
1459
1460
1461/**
1462 * Perform the actual reset.
1463 *
1464 * @thread EMT or a VUSB reset thread.
1465 */
1466static DECLCALLBACK(int) vusbDevResetWorker(PVUSBDEV pDev, bool fResetOnLinux, bool fUseTimer, PVUSBRESETARGS pArgs)
1467{
1468 uint64_t const uTimerDeadline = !fUseTimer ? 0
1469 : PDMUsbHlpTimerGet(pDev->pUsbIns, pDev->hResetTimer)
1470 + PDMUsbHlpTimerFromMilli(pDev->pUsbIns, pDev->hResetTimer, 10);
1471
1472 int rc = VINF_SUCCESS;
1473 if (pDev->pUsbIns->pReg->pfnUsbReset)
1474 rc = pDev->pUsbIns->pReg->pfnUsbReset(pDev->pUsbIns, fResetOnLinux);
1475
1476 if (pArgs)
1477 {
1478 pArgs->rc = rc;
1479 rc = VINF_SUCCESS;
1480 }
1481
1482 if (fUseTimer)
1483 {
1484 /*
1485 * We use a timer to communicate the result back to EMT.
1486 * This avoids suspend + poweroff issues, and it should give
1487 * us more accurate scheduling than making this thread sleep.
1488 */
1489 int rc2 = PDMUsbHlpTimerSet(pDev->pUsbIns, pDev->hResetTimer, uTimerDeadline);
1490 AssertReleaseRC(rc2);
1491 }
1492
1493 LogFlow(("vusbDevResetWorker: %s: returns %Rrc\n", pDev->pUsbIns->pszName, rc));
1494 return rc;
1495}
1496
1497
1498/**
1499 * Resets a device.
1500 *
1501 * Since a device reset shall take at least 10ms from the guest point of view,
1502 * it must be performed asynchronously. We create a thread which performs this
1503 * operation and ensures it will take at least 10ms.
1504 *
1505 * At times - like init - a synchronous reset is required, this can be done
1506 * by passing NULL for pfnDone.
1507 *
1508 * While the device is being reset it is in the VUSB_DEVICE_STATE_RESET state.
1509 * On completion it will be in the VUSB_DEVICE_STATE_DEFAULT state if successful,
1510 * or in the VUSB_DEVICE_STATE_DETACHED state if the rest failed.
1511 *
1512 * @returns VBox status code.
1513 *
1514 * @param pDevice Pointer to the VUSB device interface.
1515 * @param fResetOnLinux Whether it's safe to reset the device(s) on a linux
1516 * host system. See discussion of logical reconnects elsewhere.
1517 * @param pfnDone Pointer to the completion routine. If NULL a synchronous
1518 * reset is preformed not respecting the 10ms.
1519 * @param pvUser Opaque user data to pass to the done callback.
1520 * @param pVM Pointer to the VM handle for performing the done function
1521 * on the EMT thread.
1522 * @thread EMT
1523 */
1524static DECLCALLBACK(int) vusbIDeviceReset(PVUSBIDEVICE pDevice, bool fResetOnLinux,
1525 PFNVUSBRESETDONE pfnDone, void *pvUser, PVM pVM)
1526{
1527 RT_NOREF(pVM);
1528 PVUSBDEV pDev = (PVUSBDEV)pDevice;
1529 Assert(!pfnDone || pVM);
1530 LogFlow(("vusb: reset: [%s]/%i\n", pDev->pUsbIns->pszName, pDev->i16Port));
1531
1532 /*
1533 * Only one reset operation at a time.
1534 */
1535 const VUSBDEVICESTATE enmStateOld = vusbDevSetState(pDev, VUSB_DEVICE_STATE_RESET);
1536 if (enmStateOld == VUSB_DEVICE_STATE_RESET)
1537 {
1538 LogRel(("VUSB: %s: reset request is ignored, the device is already resetting!\n", pDev->pUsbIns->pszName));
1539 return VERR_VUSB_DEVICE_IS_RESETTING;
1540 }
1541
1542 /*
1543 * First, cancel all async URBs.
1544 */
1545 vusbDevCancelAllUrbs(pDev, false);
1546
1547 /* Async or sync? */
1548 if (pfnDone)
1549 {
1550 /*
1551 * Async fashion.
1552 */
1553 PVUSBRESETARGS pArgs = (PVUSBRESETARGS)RTMemTmpAlloc(sizeof(*pArgs));
1554 if (pArgs)
1555 {
1556 pArgs->pDev = pDev;
1557 pArgs->pfnDone = pfnDone;
1558 pArgs->pvUser = pvUser;
1559 pArgs->rc = VINF_SUCCESS;
1560 AssertPtrNull(pDev->pvArgs);
1561 pDev->pvArgs = pArgs;
1562 int rc = vusbDevIoThreadExec(pDev, 0 /* fFlags */, (PFNRT)vusbDevResetWorker, 4, pDev, fResetOnLinux, true, pArgs);
1563 if (RT_SUCCESS(rc))
1564 return rc;
1565
1566 RTMemTmpFree(pArgs);
1567 }
1568 /* fall back to sync on failure */
1569 }
1570
1571 /*
1572 * Sync fashion.
1573 */
1574 int rc = vusbDevResetWorker(pDev, fResetOnLinux, false, NULL);
1575 vusbDevResetDone(pDev, rc, pfnDone, pvUser);
1576 return rc;
1577}
1578
1579
1580/**
1581 * Powers on the device.
1582 *
1583 * @returns VBox status code.
1584 * @param pInterface Pointer to the device interface structure.
1585 */
1586static DECLCALLBACK(int) vusbIDevicePowerOn(PVUSBIDEVICE pInterface)
1587{
1588 PVUSBDEV pDev = (PVUSBDEV)pInterface;
1589 LogFlow(("vusbDevPowerOn: pDev=%p[%s]\n", pDev, pDev->pUsbIns->pszName));
1590
1591 /*
1592 * Check that the device is in a valid state.
1593 */
1594 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
1595 if (enmState == VUSB_DEVICE_STATE_DETACHED)
1596 {
1597 Log(("vusb: warning: attempt to power on detached device %p[%s]\n", pDev, pDev->pUsbIns->pszName));
1598 return VERR_VUSB_DEVICE_NOT_ATTACHED;
1599 }
1600 if (enmState == VUSB_DEVICE_STATE_RESET)
1601 {
1602 LogRel(("VUSB: %s: power on ignored, the device is resetting!\n", pDev->pUsbIns->pszName));
1603 return VERR_VUSB_DEVICE_IS_RESETTING;
1604 }
1605
1606 /*
1607 * Do the job.
1608 */
1609 if (enmState == VUSB_DEVICE_STATE_ATTACHED)
1610 vusbDevSetState(pDev, VUSB_DEVICE_STATE_POWERED);
1611
1612 return VINF_SUCCESS;
1613}
1614
1615
1616/**
1617 * Powers off the device.
1618 *
1619 * @returns VBox status code.
1620 * @param pInterface Pointer to the device interface structure.
1621 */
1622static DECLCALLBACK(int) vusbIDevicePowerOff(PVUSBIDEVICE pInterface)
1623{
1624 PVUSBDEV pDev = (PVUSBDEV)pInterface;
1625 LogFlow(("vusbDevPowerOff: pDev=%p[%s]\n", pDev, pDev->pUsbIns->pszName));
1626
1627 /*
1628 * Check that the device is in a valid state.
1629 */
1630 const VUSBDEVICESTATE enmState = vusbDevGetState(pDev);
1631 if (enmState == VUSB_DEVICE_STATE_DETACHED)
1632 {
1633 Log(("vusb: warning: attempt to power off detached device %p[%s]\n", pDev, pDev->pUsbIns->pszName));
1634 return VERR_VUSB_DEVICE_NOT_ATTACHED;
1635 }
1636 if (enmState == VUSB_DEVICE_STATE_RESET)
1637 {
1638 LogRel(("VUSB: %s: power off ignored, the device is resetting!\n", pDev->pUsbIns->pszName));
1639 return VERR_VUSB_DEVICE_IS_RESETTING;
1640 }
1641
1642 /*
1643 * If it's a root hub, we will have to cancel all URBs and reap them.
1644 */
1645 if (vusbDevIsRh(pDev))
1646 {
1647 PVUSBROOTHUB pRh = (PVUSBROOTHUB)pDev;
1648 VUSBIRhCancelAllUrbs(&pRh->IRhConnector);
1649 VUSBIRhReapAsyncUrbs(&pRh->IRhConnector, pDev->i16Port, 0);
1650 }
1651
1652 vusbDevSetState(pDev, VUSB_DEVICE_STATE_ATTACHED);
1653 return VINF_SUCCESS;
1654}
1655
1656
1657/**
1658 * Get the state of the device.
1659 *
1660 * @returns Device state.
1661 * @param pInterface Pointer to the device interface structure.
1662 */
1663static DECLCALLBACK(VUSBDEVICESTATE) vusbIDeviceGetState(PVUSBIDEVICE pInterface)
1664{
1665 return vusbDevGetState((PVUSBDEV)pInterface);
1666}
1667
1668
1669/**
1670 * @interface_method_impl{VUSBIDEVICE,pfnIsSavedStateSupported}
1671 */
1672static DECLCALLBACK(bool) vusbIDeviceIsSavedStateSupported(PVUSBIDEVICE pInterface)
1673{
1674 PVUSBDEV pDev = (PVUSBDEV)pInterface;
1675 bool fSavedStateSupported = RT_BOOL(pDev->pUsbIns->pReg->fFlags & PDM_USBREG_SAVED_STATE_SUPPORTED);
1676
1677 LogFlowFunc(("pInterface=%p\n", pInterface));
1678
1679 LogFlowFunc(("returns %RTbool\n", fSavedStateSupported));
1680 return fSavedStateSupported;
1681}
1682
1683
1684/**
1685 * @interface_method_impl{VUSBIDEVICE,pfnGetState}
1686 */
1687static DECLCALLBACK(VUSBSPEED) vusbIDeviceGetSpeed(PVUSBIDEVICE pInterface)
1688{
1689 PVUSBDEV pDev = (PVUSBDEV)pInterface;
1690 VUSBSPEED enmSpeed = pDev->pUsbIns->enmSpeed;
1691
1692 LogFlowFunc(("pInterface=%p, returns %u\n", pInterface, enmSpeed));
1693 return enmSpeed;
1694}
1695
1696
1697/**
1698 * The maximum number of interfaces the device can have in all of it's configuration.
1699 *
1700 * @returns Number of interfaces.
1701 * @param pDev The device.
1702 */
1703size_t vusbDevMaxInterfaces(PVUSBDEV pDev)
1704{
1705 uint8_t cMax = 0;
1706 unsigned i = pDev->pDescCache->pDevice->bNumConfigurations;
1707 while (i-- > 0)
1708 {
1709 if (pDev->pDescCache->paConfigs[i].Core.bNumInterfaces > cMax)
1710 cMax = pDev->pDescCache->paConfigs[i].Core.bNumInterfaces;
1711 }
1712
1713 return cMax;
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 Args The parameter list.
1726 *
1727 * @remarks See remarks on RTReqQueueCallV
1728 */
1729DECLHIDDEN(int) vusbDevIoThreadExecV(PVUSBDEV pDev, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args)
1730{
1731 int rc = VINF_SUCCESS;
1732 PRTREQ hReq = NULL;
1733
1734 Assert(pDev->hUrbIoThread != NIL_RTTHREAD);
1735 if (RT_LIKELY(pDev->hUrbIoThread != NIL_RTTHREAD))
1736 {
1737 uint32_t fReqFlags = RTREQFLAGS_IPRT_STATUS;
1738
1739 if (!(fFlags & VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC))
1740 fReqFlags |= RTREQFLAGS_NO_WAIT;
1741
1742 rc = RTReqQueueCallV(pDev->hReqQueueSync, &hReq, 0 /* cMillies */, fReqFlags, pfnFunction, cArgs, Args);
1743 Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
1744
1745 /* In case we are called on the I/O thread just process the request. */
1746 if ( pDev->hUrbIoThread == RTThreadSelf()
1747 && (fFlags & VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC))
1748 {
1749 int rc2 = RTReqQueueProcess(pDev->hReqQueueSync, 0);
1750 Assert(RT_SUCCESS(rc2) || rc2 == VERR_TIMEOUT); NOREF(rc2);
1751 }
1752 else
1753 vusbDevUrbIoThreadWakeup(pDev);
1754
1755 if ( rc == VERR_TIMEOUT
1756 && (fFlags & VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC))
1757 {
1758 rc = RTReqWait(hReq, RT_INDEFINITE_WAIT);
1759 AssertRC(rc);
1760 }
1761 RTReqRelease(hReq);
1762 }
1763 else
1764 rc = VERR_INVALID_STATE;
1765
1766 return rc;
1767}
1768
1769
1770/**
1771 * Executes a given function on the I/O thread.
1772 *
1773 * @returns IPRT status code.
1774 * @param pDev The USB device instance data.
1775 * @param fFlags Combination of VUSB_DEV_IO_THREAD_EXEC_FLAGS_*
1776 * @param pfnFunction The function to execute.
1777 * @param cArgs Number of arguments to the function.
1778 * @param ... The parameter list.
1779 *
1780 * @remarks See remarks on RTReqQueueCallV
1781 */
1782DECLHIDDEN(int) vusbDevIoThreadExec(PVUSBDEV pDev, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...)
1783{
1784 int rc = VINF_SUCCESS;
1785 va_list va;
1786
1787 va_start(va, cArgs);
1788 rc = vusbDevIoThreadExecV(pDev, fFlags, pfnFunction, cArgs, va);
1789 va_end(va);
1790 return rc;
1791}
1792
1793
1794/**
1795 * Executes a given function synchronously on the I/O thread waiting for it to complete.
1796 *
1797 * @returns IPRT status code.
1798 * @param pDev The USB device instance data
1799 * @param pfnFunction The function to execute.
1800 * @param cArgs Number of arguments to the function.
1801 * @param ... The parameter list.
1802 *
1803 * @remarks See remarks on RTReqQueueCallV
1804 */
1805DECLHIDDEN(int) vusbDevIoThreadExecSync(PVUSBDEV pDev, PFNRT pfnFunction, unsigned cArgs, ...)
1806{
1807 int rc = VINF_SUCCESS;
1808 va_list va;
1809
1810 va_start(va, cArgs);
1811 rc = vusbDevIoThreadExecV(pDev, VUSB_DEV_IO_THREAD_EXEC_FLAGS_SYNC, pfnFunction, cArgs, va);
1812 va_end(va);
1813 return rc;
1814}
1815
1816
1817/**
1818 * Initialize a new VUSB device.
1819 *
1820 * @returns VBox status code.
1821 * @param pDev The VUSB device to initialize.
1822 * @param pUsbIns Pointer to the PDM USB Device instance.
1823 * @param pszCaptureFilename Optional fileame to capture the traffic to.
1824 */
1825int vusbDevInit(PVUSBDEV pDev, PPDMUSBINS pUsbIns, const char *pszCaptureFilename)
1826{
1827 /*
1828 * Initialize the device data members.
1829 * (All that are Non-Zero at least.)
1830 */
1831 Assert(!pDev->IDevice.pfnReset);
1832 Assert(!pDev->IDevice.pfnPowerOn);
1833 Assert(!pDev->IDevice.pfnPowerOff);
1834 Assert(!pDev->IDevice.pfnGetState);
1835 Assert(!pDev->IDevice.pfnIsSavedStateSupported);
1836
1837 pDev->IDevice.pfnReset = vusbIDeviceReset;
1838 pDev->IDevice.pfnPowerOn = vusbIDevicePowerOn;
1839 pDev->IDevice.pfnPowerOff = vusbIDevicePowerOff;
1840 pDev->IDevice.pfnGetState = vusbIDeviceGetState;
1841 pDev->IDevice.pfnIsSavedStateSupported = vusbIDeviceIsSavedStateSupported;
1842 pDev->IDevice.pfnGetSpeed = vusbIDeviceGetSpeed;
1843 pDev->pUsbIns = pUsbIns;
1844 pDev->pNext = NULL;
1845 pDev->pNextHash = NULL;
1846 pDev->pHub = NULL;
1847 pDev->enmState = VUSB_DEVICE_STATE_DETACHED;
1848 pDev->cRefs = 1;
1849 pDev->u8Address = VUSB_INVALID_ADDRESS;
1850 pDev->u8NewAddress = VUSB_INVALID_ADDRESS;
1851 pDev->i16Port = -1;
1852 pDev->u16Status = 0;
1853 pDev->pDescCache = NULL;
1854 pDev->pCurCfgDesc = NULL;
1855 pDev->paIfStates = NULL;
1856 RTListInit(&pDev->LstAsyncUrbs);
1857 memset(&pDev->aPipes[0], 0, sizeof(pDev->aPipes));
1858 for (unsigned i = 0; i < RT_ELEMENTS(pDev->aPipes); i++)
1859 {
1860 int rc = RTCritSectInit(&pDev->aPipes[i].CritSectCtrl);
1861 AssertRCReturn(rc, rc);
1862 }
1863 pDev->hResetTimer = NIL_TMTIMERHANDLE;
1864 pDev->hSniffer = VUSBSNIFFER_NIL;
1865
1866 int rc = RTCritSectInit(&pDev->CritSectAsyncUrbs);
1867 AssertRCReturn(rc, rc);
1868
1869 /* Create the URB pool. */
1870 rc = vusbUrbPoolInit(&pDev->UrbPool);
1871 AssertRCReturn(rc, rc);
1872
1873 /* Setup request queue executing synchronous tasks on the I/O thread. */
1874 rc = RTReqQueueCreate(&pDev->hReqQueueSync);
1875 AssertRCReturn(rc, rc);
1876
1877 /*
1878 * Create the reset timer. Make sure the name is unique as we're generic code.
1879 */
1880 static uint32_t volatile s_iSeq;
1881 char szDesc[32];
1882 RTStrPrintf(szDesc, sizeof(szDesc), "VUSB Reset #%u", ASMAtomicIncU32(&s_iSeq));
1883 rc = PDMUsbHlpTimerCreate(pDev->pUsbIns, TMCLOCK_VIRTUAL, vusbDevResetDoneTimer, pDev, 0 /*fFlags*/,
1884 szDesc, &pDev->hResetTimer);
1885 AssertRCReturn(rc, rc);
1886
1887 if (pszCaptureFilename)
1888 {
1889 rc = VUSBSnifferCreate(&pDev->hSniffer, 0, pszCaptureFilename, NULL, NULL);
1890 AssertRCReturn(rc, rc);
1891 }
1892
1893 /*
1894 * Get the descriptor cache from the device. (shall cannot fail)
1895 */
1896 pDev->pDescCache = pUsbIns->pReg->pfnUsbGetDescriptorCache(pUsbIns);
1897 AssertPtr(pDev->pDescCache);
1898#ifdef VBOX_STRICT
1899 if (pDev->pDescCache->fUseCachedStringsDescriptors)
1900 {
1901 int32_t iPrevId = -1;
1902 for (unsigned iLang = 0; iLang < pDev->pDescCache->cLanguages; iLang++)
1903 {
1904 Assert((int32_t)pDev->pDescCache->paLanguages[iLang].idLang > iPrevId);
1905 iPrevId = pDev->pDescCache->paLanguages[iLang].idLang;
1906
1907 int32_t idxPrevStr = -1;
1908 PCPDMUSBDESCCACHESTRING paStrings = pDev->pDescCache->paLanguages[iLang].paStrings;
1909 unsigned cStrings = pDev->pDescCache->paLanguages[iLang].cStrings;
1910 for (unsigned iStr = 0; iStr < cStrings; iStr++)
1911 {
1912 Assert((int32_t)paStrings[iStr].idx > idxPrevStr);
1913 idxPrevStr = paStrings[iStr].idx;
1914 size_t cch = strlen(paStrings[iStr].psz);
1915 Assert(cch <= 127);
1916 }
1917 }
1918 }
1919#endif
1920
1921 /*
1922 * Allocate memory for the interface states.
1923 */
1924 size_t cbIface = vusbDevMaxInterfaces(pDev) * sizeof(*pDev->paIfStates);
1925 pDev->paIfStates = (PVUSBINTERFACESTATE)RTMemAllocZ(cbIface);
1926 AssertMsgReturn(pDev->paIfStates, ("RTMemAllocZ(%d) failed\n", cbIface), VERR_NO_MEMORY);
1927
1928 return VINF_SUCCESS;
1929}
1930
1931/*
1932 * Local Variables:
1933 * mode: c
1934 * c-file-style: "bsd"
1935 * c-basic-offset: 4
1936 * tab-width: 4
1937 * indent-tabs-mode: s
1938 * End:
1939 */
1940
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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