diff --git a/headers/os/drivers/USB3.h b/headers/os/drivers/USB3.h index 9602e1b340..e02ba5a3e0 100644 --- a/headers/os/drivers/USB3.h +++ b/headers/os/drivers/USB3.h @@ -247,6 +247,10 @@ struct usb_module_info { uint8 portIndex); status_t (*disable_port)(usb_device hub, uint8 portIndex); + + /* Cancel all pending async requests in a device control pipe */ + status_t (*cancel_queued_requests)(usb_device device); + }; diff --git a/src/add-ons/kernel/bus_managers/usb/usb.cpp b/src/add-ons/kernel/bus_managers/usb/usb.cpp index 881d1e91bd..8a65f8f871 100644 --- a/src/add-ons/kernel/bus_managers/usb/usb.cpp +++ b/src/add-ons/kernel/bus_managers/usb/usb.cpp @@ -528,6 +528,19 @@ cancel_queued_transfers(usb_pipe pipe) } +status_t +cancel_queued_requests(usb_device dev) +{ + TRACE_MODULE("cancel_queued_requests(%" B_PRId32 ")\n", dev); + ObjectBusyReleaser object(gUSBStack->GetObject(dev)); + if (!object.IsSet() || (object->Type() & USB_OBJECT_DEVICE) == 0) + return B_DEV_INVALID_PIPE; + Device *device = (Device *)object.Get(); + + return device->DefaultPipe()->CancelQueuedTransfers(false); +} + + status_t usb_ioctl(uint32 opcode, void *buffer, size_t bufferSize) { @@ -686,7 +699,8 @@ struct usb_module_info gModuleInfoV3 = { get_nth_child, // get_nth_child get_device_parent, // get_device_parent reset_port, // reset_port - disable_port // disable_port + disable_port, // disable_port + cancel_queued_requests // cancel_queued_requests //queue_bulk_v_physical // queue_bulk_v_physical }; diff --git a/src/add-ons/kernel/drivers/bus/usb/usb_raw.cpp b/src/add-ons/kernel/drivers/bus/usb/usb_raw.cpp index a07f8fe4b8..9ab7bf1930 100644 --- a/src/add-ons/kernel/drivers/bus/usb/usb_raw.cpp +++ b/src/add-ons/kernel/drivers/bus/usb/usb_raw.cpp @@ -731,14 +731,17 @@ usb_raw_ioctl(void *cookie, uint32 op, void *buffer, size_t length) } status = acquire_sem_etc(device->notify, 1, B_KILL_CAN_INTERRUPT, 0); - if (status != B_OK) - return status; + if (status != B_OK) { + gUSBModule->cancel_queued_requests(device->device); + acquire_sem(device->notify); + } command.control.status = device->status; command.control.length = device->actual_length; deviceLocker.Unlock(); - status = B_OK; + if (command.control.status == B_OK) + status = B_OK; if (inTransfer && user_memcpy(command.control.data, controlData, command.control.length) != B_OK) { status = B_BAD_ADDRESS; @@ -855,14 +858,17 @@ usb_raw_ioctl(void *cookie, uint32 op, void *buffer, size_t length) } status = acquire_sem_etc(device->notify, 1, B_KILL_CAN_INTERRUPT, 0); - if (status != B_OK) - return status; + if (status != B_OK) { + gUSBModule->cancel_queued_transfers(endpointInfo->handle); + acquire_sem(device->notify); + } command.transfer.status = device->status; command.transfer.length = device->actual_length; deviceLocker.Unlock(); - status = B_OK; + if (command.transfer.status == B_OK) + status = B_OK; if (op == B_USB_RAW_COMMAND_ISOCHRONOUS_TRANSFER) { if (user_memcpy(command.isochronous.packet_descriptors, packetDescriptors, descriptorsSize) != B_OK) {