|
From: Dan C. <cim...@ya...> - 2022-10-01 15:44:40
|
Hello,
I have a single-thread C++ program running on a linux computer, which attempts to transfer data over USB from a device. The endpoint used to transfer the data has bInterval=1ms and wMaxPacketSize=64.
The device sends one packet (30 or 40 bytes) every ~8ms. Every packet carries a sequence number, so it's possible to trace it in an USB capture. Each packet is transferred in a single USB transfer.
My program blocks 4.16ms reading from a timerfd file descriptor. It then calls libusb_handle_events_timeout_completed(); this invokes callback function OnReadCompleted() when a transfer is completed. The callback function OnReadCompleted() clears a flag and uses the data received from device. Then, if the flag is cleared, it triggers a new interrupt transfer; the buffer/length of the transfer is set large enough, so that the there's no chance of it becoming full before the transfer timeout (8ms) expires.
Essentially, the program is most of the time having an interrupt transfer ongoing (see code snippet at end of message).
Usually, while in OnReadCompleted() I'm seeing pTransfer->status == LIBUSB_TRANSFER_COMPLETED and pTransfer->actual_length > 0, and the data from device is available in pTransfer->buffer.
Sometimes however, 2 consecutive transfers have pTransfer->status == LIBUSB_TRANSFER_TIMED_OUT, pTransfer->actual_length <= 0 and pTransfer->buffer still holds the data from last successful transfer (which ended with pTransfer->status == LIBUSB_TRANSFER_COMPLETED). Prior to this taking place, all other libusb calls complete successfully.
It's always 2 consecutive transfers. Everything works fine for a few minutes, and then I'm seeing these 2 x LIBUSB_TRANSFER_TIMED_OUT for a while, and then works fine again; this seems to happen randomly, I could not relate it to any other event in the system.
>From USB capture, I could see that device does always send the two packets (which fail to appear in my callback), and the host acknowledges them.
I have tried enabling warning and errors with libusb_set_option( LIBUSB_OPTION_LOG_LEVEL) but didn't get anything relevant.
Could this (missed 2 consecutive packets) be a libusb problem?
Thanks,
Dan
================
bool transferring = false;
unsigned char rxBuf[1024] = {0};
int main() {
while (true) {
// Block 4.16ms (read from a timerfd file descriptor)
libusb_handle_events_timeout_completed(...); // Non-blocking, use 0 timeval
// The transfer completion callback clears transferring flag
if (!transferring) {
// Initiate an interrupt transfer device -> host
const int TIMEOUT_MS = 8;
libusb_transfer* pTransfer = libusb_alloc_transfer(0); // Interrupt transfer
libusb_fill_interrupt_transfer(pTransfer, ... rxBuf, sizeof(rxBuf), OnReadCompleted, TIMEOUT_MS);
libusb_submit_transfer(pTransfer);
if () { // All libusb calls succeded
transferring = true;
}
}
}
}
// The callback function invoked by libusb upon transfer completion
void OnReadCompleted(libusb_transfer* pTransfer, ...)
{
transferring = false;
// Do something with data received from device
}
|