USB bus drivers: Return error when combining other transfers with a fragmented one.

The drivers do not support this properly at present, they would
run the other transfers interspersed with fragments from the fragemented one,
which is obviously the wrong thing to do.

No USB device drivers seem to do this at present (it would cause data
corruption if they had.)

Fixes #17275.
This commit is contained in:
Augustin Cavalier
2021-09-27 16:28:01 -04:00
parent 1681f7f4fe
commit ae61e1b716
4 changed files with 45 additions and 0 deletions
+13
View File
@@ -1547,6 +1547,19 @@ EHCI::AddPendingTransfer(Transfer *transfer, ehci_qh *queueHead,
return B_ERROR;
}
// We do not support queuing other transfers in tandem with a fragmented one.
transfer_data *it = fFirstTransfer;
while (it) {
if (it->transfer && it->transfer->TransferPipe() == transfer->TransferPipe()
&& it->transfer->IsFragmented()) {
TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n");
Unlock();
delete data;
return B_DEV_RESOURCE_CONFLICT;
}
}
if (fLastTransfer)
fLastTransfer->link = data;
else
+11
View File
@@ -1451,6 +1451,17 @@ OHCI::_SubmitTransfer(Transfer *transfer)
= (ohci_endpoint_descriptor *)pipe->ControllerCookie();
MutexLocker endpointLocker(endpoint->lock);
// We do not support queuing other transfers in tandem with a fragmented one.
transfer_data *it = fFirstTransfer;
while (it) {
if (it->transfer && it->transfer->TransferPipe() == pipe && it->transfer->IsFragmented()) {
TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n");
_FreeDescriptorChain(firstDescriptor);
return B_DEV_RESOURCE_CONFLICT;
}
}
result = _AddPendingTransfer(transfer, endpoint, firstDescriptor,
firstDescriptor, lastDescriptor, directionIn);
if (result < B_OK) {
+13
View File
@@ -1065,6 +1065,19 @@ UHCI::AddPendingTransfer(Transfer *transfer, Queue *queue,
return B_ERROR;
}
// We do not support queuing other transfers in tandem with a fragmented one.
transfer_data *it = fFirstTransfer;
while (it) {
if (it->transfer && it->transfer->TransferPipe() == transfer->TransferPipe()
&& it->transfer->IsFragmented()) {
TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n");
Unlock();
delete data;
return B_DEV_RESOURCE_CONFLICT;
}
}
if (fLastTransfer)
fLastTransfer->link = data;
if (!fFirstTransfer)
+8
View File
@@ -1846,6 +1846,14 @@ XHCI::_LinkDescriptorForPipe(xhci_td *descriptor, xhci_endpoint *endpoint)
return B_BAD_VALUE;
}
// We do not support queuing other transfers in tandem with a fragmented one.
if (endpoint->td_head != NULL && endpoint->td_head->transfer != NULL
&& endpoint->td_head->transfer->IsFragmented()) {
TRACE_ERROR("cannot submit transfer: a fragmented transfer is queued\n");
mutex_unlock(&endpoint->lock);
return B_DEV_RESOURCE_CONFLICT;
}
endpoint->used++;
descriptor->next = endpoint->td_head;
endpoint->td_head = descriptor;