The HCI then copies any request data into the URB if it's an host2dev transfer. It then submits the URB by calling the pfnSubmitUrb roothub method.
pfnSubmitUrb will start by checking if it knows the device address, and if it doesn't the URB is completed with a device-not-ready error. When the device address is known to it, action is taken based on the kind of transfer it is. There are four kinds of transfers: 1. control, 2. bulk, 3. interrupt, and 4. isochronous. In either case something eventually ends up being submitted to the device.
If an URB fails submitting, may or may not be completed. This depends on heuristics in some cases and on the kind of failure in others. If pfnSubmitUrb returns a failure, the HCI should retry submitting it at a later time. If pfnSubmitUrb returns success the URB is submitted, and it can even been completed.
The URB is in the IN_FLIGHT state from the time it's successfully submitted and till it's reaped or cancelled.
When an URB transfer or in some case submit failure occurs, the pfnXferError callback of the HCI is consulted about what to do. If pfnXferError indicates that the URB should be retried, pfnSubmitUrb will fail. If it indicates that it should fail, the URB will be completed.
Completing an URB means that the URB status is set and the HCI pfnXferCompletion callback is invoked with the URB. The HCI is the supposed to report the transfer status to the guest OS. After completion the URB is freed and returned to the pool, unless it was cancelled. If it was cancelled it will have to await reaping before it's actually freed.
What makes the control transfer complicated is that for a host2dev request the URB is assembled from the SETUP and DATA stage, and for a dev2host request the returned data must be kept around for the DATA stage. For both transfer directions the status of the transfer has to be kept around for the STATUS stage.
To complicate matters futher, VUSB must intercept and in some cases emulate some of the standard requests in order to keep the virtual device state correct and provide the correct virtualization of a device.