Fix usb-arc driver: the driver would prematurely mark a transfer as complete whereas only a part of it actually is, check the active of the TDs to avoid that. This should fix some HID+UMS bugs.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25328 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Amaury Pouly 2010-03-25 13:45:19 +00:00
parent a4ff42d146
commit 1dd216ba06

View file

@ -917,20 +917,33 @@ static void transfer_completed(void)
int pipe = ep * 2 + dir;
if (mask & pipe2mask[pipe]) {
struct queue_head* qh = &qh_array[pipe];
if(qh->wait) {
qh->wait=0;
wakeup_signal(&transfer_completion_signal[pipe]);
}
int length=0;
struct transfer_descriptor* td=&td_array[pipe*NUM_TDS_PER_EP];
while(td!=(struct transfer_descriptor*)DTD_NEXT_TERMINATE && td!=0)
{
/* It seems that the controller sets the pipe bit to one even if the TD
* dosn't have the IOC bit set. So we have the rely the active status bit
* to check that all the TDs of the transfer are really finished and let
* the transfer continue if it's no the case */
if(td->size_ioc_sts & DTD_STATUS_ACTIVE)
{
logf("skip half finished transfer");
goto Lskip;
}
length += ((td->reserved & DTD_RESERVED_LENGTH_MASK) -
((td->size_ioc_sts & DTD_PACKET_SIZE) >> DTD_LENGTH_BIT_POS));
td=(struct transfer_descriptor*) td->next_td_ptr;
}
if(qh->wait) {
qh->wait=0;
wakeup_signal(&transfer_completion_signal[pipe]);
}
usb_core_transfer_complete(ep, dir?USB_DIR_IN:USB_DIR_OUT,
qh->status, length);
Lskip:
continue;
}
}
}