I want to read isochronous data from my usb webcam. I am using Windows 11, C++, and the device’s driver is not WinUSB. So I am using UsbDK for the backend of libusb.
What I want is this:
This is the capture result by using USBPCap to capture the stream of USB Webcam data.
As the red squared area, I think those are the RAW Video data which is formatted as “YUV2”.
So I want to get them as text with cpp code.
I could easily get the enum of USB devices attached to my PC. And I could send a transfer to the Webcam. But I can’t proceed anymore because the transfer’s result seems strange.
Here is the code:
#include <stdio.h>
#include <io.h>
#include <stdlib.h>
#include <string.h>
#include <libusb-1.0/libusb.h>
#include <signal.h>
#include <errno.h>
//----------------------------------------------------------------------------
// Constant
//----------------------------------------------------------------------------
#define ID_VENDOR 0X174F
#define ID_PRODUCT 0X2459
#define EP_ISO_IN 0x81
#define EP_BULK_IN 0x81
#define NUM_ISO_PACKET 0x10
#define EP_PACKET_SIZE 0x80
//----------------------------------------------------------------------------
// Global variable
//----------------------------------------------------------------------------
static int do_exit = 0;
static libusb_device_handle* LIBUSB_CALL dev_handle = NULL;
static int counter = 0;
uint8_t buffer[NUM_ISO_PACKET * EP_PACKET_SIZE];
//----------------------------------------------------------------------------
void signal_handler(int param)
{
printf("SIGNAL %d", param);
do_exit = 1;
}
static void scan_devices()
{
libusb_device** devs;
libusb_device* dev;
int i = 0, cnt;
cnt = libusb_get_device_list(NULL, &devs);
if (cnt < 0)
{
return;
}
while ((dev = devs[i++]) != NULL)
{
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0)
{
printf("failed to get device descriptorn");
return;
}
printf("%04X:%04X (bus:%d, device: %d)n",
desc.idVendor,
desc.idProduct,
libusb_get_bus_number(dev),
libusb_get_device_address(dev));
if (desc.idVendor == ID_VENDOR && desc.idProduct == ID_PRODUCT)
{
printf(" endpoint: %02X (%d %d)n",
EP_ISO_IN,
libusb_get_max_packet_size(dev, EP_ISO_IN),
libusb_get_max_iso_packet_size(dev, EP_ISO_IN));
}
}
libusb_free_device_list(devs, 1);
}
static void LIBUSB_CALL cb_xfr(struct libusb_transfer* xfr)
{
uint16_t i, len = 0;
counter++;
printf("nnCallbackFunction!!!nn");
//Initalize buffer 16byte
//uint8_t *recv = malloc(EP_PACKET_SIZE * NUM_ISO_PACKET);
//uint8_t *recv_next = recv;
if (xfr->status != LIBUSB_TRANSFER_COMPLETED)
{
printf("Error transfer status: %dn", xfr->status);
libusb_free_transfer(xfr);
exit(3);
}
printf("[%d] XFR length:%u, actual_length:%un", counter, xfr->length, xfr->actual_length);
if (xfr->type == LIBUSB_TRANSFER_TYPE_ISOCHRONOUS)
{
for (i = 0; i < xfr->num_iso_packets; i++)
{
struct libusb_iso_packet_descriptor* pack = &xfr->iso_packet_desc[i];
if (pack->status != LIBUSB_TRANSFER_COMPLETED)
{
printf("Error pack %u status %dn", i, pack->status);
//exit(5);
}
else {
printf("pack%u length:%u, actual_length:%un", i, pack->length, pack->actual_length);
//const uint8_t *data = libusb_get_iso_packet_buffer_simple(xfr, i);
for (i = 0; i < pack->actual_length; i++)
{
printf("%02d ", xfr->buffer[i]);
}
printf("n");
}
}
}
//Sanity check. If this is true, we've overflowed the recv buffer.
if (len > EP_PACKET_SIZE * xfr->num_iso_packets)
{
printf("Error: incoming transfer had more data than we thought.n");
exit(1);
}
//printf("re-submit transfern");
if (libusb_submit_transfer(xfr) < 0)
{
printf("Error re-submit transfern");
exit(1);
}
}
static int test_iso(uint8_t endpoint)
{
static struct libusb_transfer* xfr;
xfr = libusb_alloc_transfer(NUM_ISO_PACKET);
if (!xfr)
return LIBUSB_ERROR_NO_MEM;
memset(buffer, 3, sizeof(buffer));
libusb_fill_iso_transfer(xfr, dev_handle, endpoint, buffer,
sizeof(buffer), NUM_ISO_PACKET, cb_xfr, NULL, 0);
libusb_set_iso_packet_lengths(xfr, EP_PACKET_SIZE);
//libusb_fill_bulk_transfer(xfr, dev_handle, endpoint, buffer, 64, cb_xfr, NULL, 0);
return libusb_submit_transfer(xfr);
}
int main(void)
{
int err_code;
//Signal Handler
signal(SIGINT, signal_handler);
signal(SIGTERM, signal_handler);
//Init LIBUSB
err_code = libusb_init(NULL);
if (err_code != 0)
{
printf("Error initializing libusb %sn", libusb_error_name(err_code));
exit(1);
}
//Set debug level
libusb_set_option(NULL, LIBUSB_OPTION_USE_USBDK);
libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_DEBUG);
//PRINT VERSION LIBUSB
const struct libusb_version* version = libusb_get_version();
printf("libusb version %d.%d.%dn", version->major, version->minor, version->micro);
//PRINT DEVICES LIST
scan_devices();
// GET USB DEVICE HANDLE
dev_handle = libusb_open_device_with_vid_pid(NULL, ID_VENDOR, ID_PRODUCT);
if (!dev_handle)
{
printf("Error finding USB devicen");
goto out;
}
printf("found USB device %02X:%02Xn", ID_VENDOR, ID_PRODUCT);
// Lock interface 1
printf("claiming interface 1n");
err_code = libusb_claim_interface(dev_handle, 1);
if (err_code < 0)
{
printf("Error claiming interface 1n");
goto out;
}
err_code = test_iso(EP_ISO_IN);
if (err_code < 0)
{
printf("Error test isochronousn code:%d %sn", err_code, libusb_error_name(err_code));
}
// handle pending event in blocking mode
//*
printf("start pending loopn");
while (!do_exit)
{
err_code = libusb_handle_events(NULL);
if (err_code != LIBUSB_SUCCESS)
break;
}//*/
// Release interface 1
printf("release interface 1n");
libusb_release_interface(dev_handle, 1);
//EXIT LIBUSB
out:
if (dev_handle)
{
libusb_close(dev_handle);
}
libusb_exit(NULL);
return err_code;
}
this is referred from the sample https://github.com/nodtem66/test-iso-usb/blob/master/test_iso/main.c#L24
I just added a line
libusb_set_option(NULL, LIBUSB_OPTION_USE_USBDK);
Because as I mentionned before, my device webcam doesn’t have WinUSB driver.
And the transfer’s result is like:
libusb version 1.0.27
[timestamp] [threadID] facility level [function call] <message>
--------------------------------------------------------------------------------
[ 0.005883] [000042f0] libusb: debug [libusb_get_device_list]
[ 0.006081] [000042f0] libusb: debug [libusb_get_device_descriptor]
174F:2459 (bus:1, device: 4)
[ 0.006163] [000042f0] libusb: debug [parse_configuration] skipping descriptor 0xb
[ 0.006165] [0000115c] libusb: debug [windows_iocp_thread] I/O completion thread started
[ 0.006194] [000042f0] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.006299] [000042f0] libusb: debug [parse_endpoint] skipping descriptor 0xb
[ 0.006338] [000042f0] libusb: debug [parse_configuration] skipping descriptor 0xb
[ 0.006367] [000042f0] libusb: debug [parse_endpoint] skipping descriptor 0x25
[ 0.006494] [000042f0] libusb: debug [parse_endpoint] skipping descriptor 0xb
endpoint: 81 (128 128)
[ 0.006574] [000042f0] libusb: debug [libusb_get_device_descriptor]
3554:FC03 (bus:2, device: 2)
[ 0.006623] [000042f0] libusb: debug [libusb_get_device_descriptor]
0BDA:4852 (bus:2, device: 4)
[ 0.006671] [000042f0] libusb: debug [libusb_get_device_descriptor]
04F3:0C58 (bus:2, device: 5)
[ 0.006781] [000042f0] libusb: debug [libusb_unref_device] destroy device 1.4
[ 0.006844] [000042f0] libusb: debug [libusb_unref_device] destroy device 2.2
[ 0.006897] [000042f0] libusb: debug [libusb_unref_device] destroy device 2.4
[ 0.006948] [000042f0] libusb: debug [libusb_unref_device] destroy device 2.5
[ 0.007002] [000042f0] libusb: debug [libusb_get_device_list]
[ 0.007163] [000042f0] libusb: debug [libusb_get_device_descriptor]
[ 0.007206] [000042f0] libusb: debug [libusb_open] open 1.4
[ 0.205676] [000042f0] libusb: debug [libusb_unref_device] destroy device 2.2
[ 0.205858] [000042f0] libusb: debug [libusb_unref_device] destroy device 2.4
[ 0.205933] [000042f0] libusb: debug [libusb_unref_device] destroy device 2.5
found USB device 174F:2459
claiming interface 1
[ 0.209936] [000042f0] libusb: debug [libusb_claim_interface] interface 1
[ 0.212067] [000042f0] libusb: debug [libusb_submit_transfer] transfer 000001CB15A6C880
start pending loop
[ 0.214287] [0000115c] libusb: debug [windows_iocp_thread] transfer 000001CB15A6C880 completed, length 0
[ 0.214827] [000042f0] libusb: debug [libusb_handle_events_timeout_completed] doing our own event handling
[ 0.216250] [000042f0] libusb: debug [handle_events] event sources modified, reallocating event data
[ 0.216995] [000042f0] libusb: debug [usbi_wait_for_events] WaitForMultipleObjects() for 2 HANDLEs with timeout in 60000ms
[ 0.217851] [000042f0] libusb: debug [usbi_wait_for_events] WaitForMultipleObjects() returned 0
[ 0.218577] [000042f0] libusb: debug [handle_event_trigger] event triggered
[ 0.219050] [000042f0] libusb: debug [windows_handle_transfer_completion] handling transfer 000001CB15A6C880 completion with errcode 1168, length 0
[ 0.219999] [000042f0] libusb: error [windows_handle_transfer_completion] detected I/O error 1168: [1168] Element not found.
[ 0.220782] [000042f0] libusb: debug [usbi_handle_transfer_completion] transfer 000001CB15A6C880 has callback 00007FF7ACE618A0
CallbackFunction!!!
Error transfer status: 1
[ 0.255298] [000042f0] libusb: debug [libusb_free_transfer] transfer 000001CB15A6C880
D:Codeusbcatchandthrowx64Debugusbcatchandthrow.exe exited...
I can’t proceed anymore. Can anyone help me please..?