#pragma once namespace Incart::Usb { #include "libusb-1.0/no_warnings_libusb.h" #include "UsbEndPointReader.h" template class UsbReadTransfer { static_assert(std::is_base_of::value, "TSender must derive from UsbEndPointReader"); public: static void callback(libusb_transfer* transfer) { int result = transfer->status; bool isTransferred = false; TSender* obj = static_cast(transfer->user_data); if (result == LIBUSB_TRANSFER_COMPLETED) { obj->setReceivedBytesCount(transfer->actual_length); } else if ((result == LIBUSB_TRANSFER_TIMED_OUT) || (result == LIBUSB_TRANSFER_CANCELLED)) { obj->setReceivedBytesCount(0); } else { std::string errorText = obj->getName().toStdString() + " callback error: " + std::to_string(result) + " " + libusb_strerror(result); obj->getUsb()->logError(errorText); if (result == LIBUSB_TRANSFER_STALL) { obj->setReceivedBytesCount(0); obj->getUsb()->logInfo(std::string("clear halt ") + obj->getName().toStdString()); result = libusb_clear_halt(transfer->dev_handle, transfer->endpoint); if (result != LIBUSB_SUCCESS) { errorText = obj->getName().toStdString() + " libusb_clear_halt error : " + std::to_string(result) + " " + libusb_strerror(result); obj->getUsb()->logError(errorText); } else { // Пытаемся переотправить transfer isTransferred = true; obj->setIsTransferred(false); result = libusb_submit_transfer(transfer); if (result != LIBUSB_SUCCESS) { errorText = obj->getName().toStdString() + " re-submitting transfer error : " + std::to_string(result) + " " + libusb_strerror(result); } } } if (result != LIBUSB_SUCCESS) { obj->deleteTransfer(); obj->getUsb()->logError(errorText); obj->getUsb()->setLastTransferStatus(result); } } obj->setIsTransferred(isTransferred); // флаг завершения транзакции } }; } // namespace Incart::Usb