int libusb_cancel_transfer(struct libusb_transfer* transfer) { transfer_wrapper* wrapper = GetWrapper(transfer); transfer->status = LIBUSB_TRANSFER_CANCELLED; int ret = usb_cancel_async(wrapper->usb); // 0 on success // LIBUSB_ERROR_NOT_FOUND if the transfer is already complete or cancelled. // a LIBUSB_ERROR code on failure return(ret); }
DWORD TransferThreadProc(struct BENCHMARK_TRANSFER_PARAM* transferParam) { int ret, i; struct BENCHMARK_TRANSFER_HANDLE* handle; char* data; transferParam->IsRunning = TRUE; while (!transferParam->Test->IsCancelled) { data = NULL; handle = NULL; if (transferParam->Test->TransferMode == TRANSFER_MODE_SYNC) { ret = TransferSync(transferParam); if (ret >= 0) data = transferParam->Buffer; } else if (transferParam->Test->TransferMode == TRANSFER_MODE_ASYNC) { ret = TransferAsync(transferParam, &handle); if ((handle) && ret >= 0) data = handle->Data; } else { CONERR("invalid transfer mode %d\n",transferParam->Test->TransferMode); goto Done; } if (ret < 0) { // The user pressed 'Q'. if (transferParam->Test->IsUserAborted) break; // Transfer timed out if (ret == TRANSFER_TIMEDOUT) { transferParam->TotalTimeoutCount++; transferParam->RunningTimeoutCount++; CONWRN("Timeout #%d %s on Ep%02Xh..\n", transferParam->RunningTimeoutCount, TRANSFER_DISPLAY(transferParam,"reading","writing"), transferParam->Ep.bEndpointAddress); if (transferParam->RunningTimeoutCount > transferParam->Test->Retry) break; } else { // An error (other than a timeout) occured. // usb_strerror()is not thread safe and should not be used // in a multi-threaded app. It's used here because // this is a test program. // transferParam->TotalErrorCount++; transferParam->RunningErrorCount++; CONERR("failed %s! %d of %d ret=%d: %s\n", TRANSFER_DISPLAY(transferParam,"reading","writing"), transferParam->RunningErrorCount, transferParam->Test->Retry+1, ret, usb_strerror()); usb_resetep(transferParam->Test->DeviceHandle, transferParam->Ep.bEndpointAddress); if (transferParam->RunningErrorCount > transferParam->Test->Retry) break; } ret = 0; } else { if (ret < transferParam->Test->BufferSize && !transferParam->Test->IsCancelled) { if (ret > 0) { transferParam->ShortTransferCount++; CONWRN("Short transfer on Ep%02Xh expected %d got %d.\n", transferParam->Ep.bEndpointAddress, transferParam->Test->BufferSize, ret); } else { CONWRN("Zero-length transfer on Ep%02Xh expected %d.\n", transferParam->Ep.bEndpointAddress, transferParam->Test->BufferSize); transferParam->TotalErrorCount++; transferParam->RunningErrorCount++; if (transferParam->RunningErrorCount > transferParam->Test->Retry) break; usb_resetep(transferParam->Test->DeviceHandle, transferParam->Ep.bEndpointAddress); } } else { transferParam->RunningErrorCount = 0; transferParam->RunningTimeoutCount = 0; } if ((transferParam->Test->Verify) && (transferParam->Ep.bEndpointAddress & USB_ENDPOINT_DIR_MASK)) { VerifyData(transferParam, data, ret); } } EnterCriticalSection(&DisplayCriticalSection); if (!transferParam->StartTick && transferParam->Packets >= 0) { transferParam->StartTick = GetTickCount(); transferParam->LastStartTick = transferParam->StartTick; transferParam->LastTick = transferParam->StartTick; transferParam->LastTransferred = 0; transferParam->TotalTransferred = 0; transferParam->Packets = 0; } else { if (!transferParam->LastStartTick) { transferParam->LastStartTick = transferParam->LastTick; transferParam->LastTransferred = 0; } transferParam->LastTick = GetTickCount(); transferParam->LastTransferred += ret; transferParam->TotalTransferred += ret; transferParam->Packets++; } LeaveCriticalSection(&DisplayCriticalSection); } Done: for (i=0; i < transferParam->Test->BufferCount; i++) { if (transferParam->TransferHandles[i].Context) { if (transferParam->TransferHandles[i].InUse) { if ((ret = usb_cancel_async(transferParam->TransferHandles[i].Context)) < 0) if (!transferParam->Test->IsUserAborted) CONERR("failed cancelling transfer! ret=%d\n",ret); transferParam->TransferHandles[i].InUse=FALSE; } usb_free_async(&transferParam->TransferHandles[i].Context); } } transferParam->IsRunning = FALSE; return 0; }