diff --git a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp index 31c92e7f3d..4ec27dc18a 100644 --- a/src/add-ons/kernel/bus_managers/usb/Pipe.cpp +++ b/src/add-ons/kernel/bus_managers/usb/Pipe.cpp @@ -23,7 +23,7 @@ Pipe::~Pipe() { PutUSBID(); - CancelQueuedTransfers(true); + Pipe::CancelQueuedTransfers(true); GetBusManager()->NotifyPipeChange(this, USB_CHANGE_DESTROYED); } @@ -334,6 +334,10 @@ ControlPipe::ControlPipe(Object *parent) ControlPipe::~ControlPipe() { + // We do this here in case a submitted request is still running. + PutUSBID(); + ControlPipe::CancelQueuedTransfers(true); + if (fNotifySem >= 0) delete_sem(fNotifySem); mutex_lock(&fSendRequestLock); @@ -465,3 +469,18 @@ ControlPipe::QueueRequest(uint8 requestType, uint8 request, uint16 value, delete transfer; return result; } + + +status_t +ControlPipe::CancelQueuedTransfers(bool force) +{ + if (force && fNotifySem >= 0) { + // There is likely a transfer currently running; we need to cancel it + // manually, as callbacks are not invoked when force-cancelling. + fTransferStatus = B_CANCELED; + fActualLength = 0; + release_sem_etc(fNotifySem, 1, B_RELEASE_IF_WAITING_ONLY); + } + + return Pipe::CancelQueuedTransfers(force); +} diff --git a/src/add-ons/kernel/bus_managers/usb/usb_private.h b/src/add-ons/kernel/bus_managers/usb/usb_private.h index e129393892..a5bd1ba43d 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb_private.h +++ b/src/add-ons/kernel/bus_managers/usb/usb_private.h @@ -341,7 +341,7 @@ virtual void SetDataToggle(bool toggle) { fDataToggle = toggle; } status_t SubmitTransfer(Transfer *transfer); - status_t CancelQueuedTransfers(bool force); +virtual status_t CancelQueuedTransfers(bool force); void SetControllerCookie(void *cookie) { fControllerCookie = cookie; } @@ -414,6 +414,8 @@ static void SendRequestCallback(void *cookie, usb_callback_func callback, void *callbackCookie); +virtual status_t CancelQueuedTransfers(bool force); + private: mutex fSendRequestLock; sem_id fNotifySem;