Skip to content

Commit

Permalink
a more safe way to detach an actively running vusb
Browse files Browse the repository at this point in the history
When a device is actively running with iso transfer, detach process is
used to be freezed. This is due to that iso transfers are requested
to the plugged-out device. Therefore, let an invalidated vusb deny
a subsequent request.
  • Loading branch information
cezanne committed Jan 3, 2021
1 parent 29798a2 commit b1d980a
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 21 deletions.
21 changes: 2 additions & 19 deletions driver/vhci_ude/vhci_ep.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,18 +159,6 @@ ep_add(_In_ UDECXUSBDEVICE udev, _In_ PUDECX_USB_ENDPOINT_INIT_AND_METADATA epcr
return status;
}

static VOID
release_ep(PUDECX_ENDPOINTS_CONFIGURE_PARAMS params)
{
TRD(VUSB, "Enter: ReleasedEndpointsCount=%d", params->ReleasedEndpointsCount);

for (ULONG i = 0; i < params->ReleasedEndpointsCount; i++) {
pctx_ep_t ep = TO_EP(params->ReleasedEndpoints[i]);
WdfIoQueuePurgeSynchronously(ep->queue);
TRD(VUSB, "Released ep->addr=0x%x!", ep->addr);
}
}

static NTSTATUS
set_intf_for_ep(pctx_vusb_t vusb, WDFREQUEST req, PUDECX_ENDPOINTS_CONFIGURE_PARAMS params)
{
Expand Down Expand Up @@ -215,13 +203,6 @@ ep_configure(_In_ UDECXUSBDEVICE udev, _In_ WDFREQUEST req, _In_ PUDECX_ENDPOINT

TRD(VUSB, "Enter: %!epconf!", params->ConfigureType);

release_ep(params);
if ((params->ConfigureType == UdecxEndpointsConfigureTypeEndpointsReleasedOnly) || (vusb->invalid == TRUE)) {
WdfRequestComplete(req, status);
TRD(VUSB, "Leave: %!STATUS!", status);
return;
}

switch (params->ConfigureType) {
case UdecxEndpointsConfigureTypeDeviceInitialize:
/* FIXME: UDE framework seems to not call SET CONFIGURATION if a USB has multiple interfaces.
Expand All @@ -236,6 +217,8 @@ ep_configure(_In_ UDECXUSBDEVICE udev, _In_ WDFREQUEST req, _In_ PUDECX_ENDPOINT
case UdecxEndpointsConfigureTypeInterfaceSettingChange:
status = set_intf_for_ep(vusb, req, params);
break;
case UdecxEndpointsConfigureTypeEndpointsReleasedOnly:
break;
default:
TRE(VUSB, "unhandled configure type: %!epconf!", params->ConfigureType);
break;
Expand Down
8 changes: 7 additions & 1 deletion driver/vhci_ude/vhci_plugout.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,21 @@ vusb_plugout(pctx_vusb_t vusb)
{
NTSTATUS status;

/*
* invalidate first to prevent requests from an upper layer.
* If requests are consistently fed into a vusb about to be plugged out,
* a live deadlock may occur where vusb aborts pending urbs indefinately.
*/
vusb->invalid = TRUE;
abort_pending_req_read(vusb);
abort_all_pending_urbrs(vusb);

status = UdecxUsbDevicePlugOutAndDelete(vusb->ude_usbdev);
if (NT_ERROR(status)) {
vusb->invalid = FALSE;
TRD(PLUGIN, "failed to plug out: %!STATUS!", status);
return status;
}
vusb->invalid = TRUE;
return STATUS_SUCCESS;
}

Expand Down
6 changes: 5 additions & 1 deletion driver/vhci_ude/vhci_queue_ep.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ internal_device_control(_In_ WDFQUEUE queue, _In_ WDFREQUEST req,
TRE(EP, "unexpected ioctl: %!IOCTL!", ioctl_code);
}
else {
status = submit_req_urb(*TO_PEP(queue), req);
pctx_ep_t ep = *TO_PEP(queue);
if (ep->vusb->invalid)
status = STATUS_DEVICE_DOES_NOT_EXIST;
else
status = submit_req_urb(*TO_PEP(queue), req);
}

if (status != STATUS_PENDING)
Expand Down

0 comments on commit b1d980a

Please sign in to comment.