Discussion:
[libusb] LIBUSB_TRANSFER_ERROR occasionally returned
Jirawat I.
2015-02-12 07:44:42 UTC
Permalink
Hello

I used Silabs C8051F380 for a device send the isochronous 16-byte packet.
My host program on ArchLinux can receive the packet normally. However,
after a long running, my host program return LIBUSB_TRANSFER_ERROR every
time my callback function resubmit the transfer.

How can I deal this problem?
Should I free this problematic transfer and create a new one?

Thank in advance

Best Regards
-------------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <libusb-1.0/libusb.h>
#include <signal.h>
#include <errno.h>

//----------------------------------------------------------------------------
// Constant
//----------------------------------------------------------------------------
#define ID_VENDOR 0x10C4
#define ID_PRODUCT 0x8846
#define EP_ISO_IN 0x83
#define NUM_ISO_PACKET 0x01
#define EP_PACKET_SIZE 0x10
//----------------------------------------------------------------------------
// 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 descriptor\n");
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++;
//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: %d\n", xfr->status);
libusb_free_transfer(xfr);
exit(3);
}
printf("[%d] XFR length:%u, actual_length:%u\n", 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 %d\n",i, pack->status);
//exit(5);
} else {
printf("pack%u length:%u, actual_length:%u\n",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 transfer\n");
if (libusb_submit_transfer(xfr) < 0)
{
printf("Error re-submit transfer\n");
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 %s\n", libusb_error_name(err_code));
exit(1);
}
//Set debug level
//libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_DEBUG);
//PRINT VERSION LIBUSB
const struct libusb_version *version = libusb_get_version();
printf("libusb version %d.%d.%d\n", 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 device\n");
goto out;
}
printf("found USB device %02X:%02X\n", ID_VENDOR, ID_PRODUCT);
// Lock interface 1
printf("claiming interface 0\n");
err_code = libusb_claim_interface(dev_handle, 0);
if (err_code < 0)
{
printf("Error claiming interface 0\n");
goto out;
}
err_code = test_iso(EP_ISO_IN);
if (err_code < 0)
{
printf("Error test isochronous\n code:%d %s\n", err_code,
libusb_error_name(err_code));
}
// handle pending event in blocking mode
printf("start pending loop\n");
while (!do_exit)
{
err_code = libusb_handle_events(NULL);
if (err_code != LIBUSB_SUCCESS)
break;
}
// Release interface 1
printf("release interface 1\n");
libusb_release_interface(dev_handle, 0);
//EXIT LIBUSB
out:
if (dev_handle)
{
libusb_close(dev_handle);
}
libusb_exit(NULL);
return err_code;
}
Chris Dickens
2015-02-12 08:05:05 UTC
Permalink
It would be most useful to have a debug log. Run the program with
LIBUSB_DEBUG=4 in the environment, or uncomment the call to
libusb_set_debug().

No need to include the entire log, just the relevant section when the
transfers start failing.

Regards,
Chris
Post by Jirawat I.
Hello
I used Silabs C8051F380 for a device send the isochronous 16-byte packet.
My host program on ArchLinux can receive the packet normally. However,
after a long running, my host program return LIBUSB_TRANSFER_ERROR every
time my callback function resubmit the transfer.
How can I deal this problem?
Should I free this problematic transfer and create a new one?
Thank in advance
Best Regards
-------------------------------------------------------------------------------------------------------------------------------
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <libusb-1.0/libusb.h>
#include <signal.h>
#include <errno.h>
//----------------------------------------------------------------------------
// Constant
//----------------------------------------------------------------------------
#define ID_VENDOR 0x10C4
#define ID_PRODUCT 0x8846
#define EP_ISO_IN 0x83
#define NUM_ISO_PACKET 0x01
#define EP_PACKET_SIZE 0x10
//----------------------------------------------------------------------------
// 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 descriptor\n");
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++;
//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: %d\n", xfr->status);
libusb_free_transfer(xfr);
exit(3);
}
printf("[%d] XFR length:%u, actual_length:%u\n", 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 %d\n",i, pack->status);
//exit(5);
} else {
printf("pack%u length:%u, actual_length:%u\n",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 transfer\n");
if (libusb_submit_transfer(xfr) < 0)
{
printf("Error re-submit transfer\n");
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 %s\n", libusb_error_name(err_code));
exit(1);
}
//Set debug level
//libusb_set_debug(NULL, LIBUSB_LOG_LEVEL_DEBUG);
//PRINT VERSION LIBUSB
const struct libusb_version *version = libusb_get_version();
printf("libusb version %d.%d.%d\n", 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 device\n");
goto out;
}
printf("found USB device %02X:%02X\n", ID_VENDOR, ID_PRODUCT);
// Lock interface 1
printf("claiming interface 0\n");
err_code = libusb_claim_interface(dev_handle, 0);
if (err_code < 0)
{
printf("Error claiming interface 0\n");
goto out;
}
err_code = test_iso(EP_ISO_IN);
if (err_code < 0)
{
printf("Error test isochronous\n code:%d %s\n", err_code,
libusb_error_name(err_code));
}
// handle pending event in blocking mode
printf("start pending loop\n");
while (!do_exit)
{
err_code = libusb_handle_events(NULL);
if (err_code != LIBUSB_SUCCESS)
break;
}
// Release interface 1
printf("release interface 1\n");
libusb_release_interface(dev_handle, 0);
//EXIT LIBUSB
if (dev_handle)
{
libusb_close(dev_handle);
}
libusb_exit(NULL);
return err_code;
}
------------------------------------------------------------------------------
Dive into the World of Parallel Programming. The Go Parallel Website,
sponsored by Intel and developed in partnership with Slashdot Media, is
your
hub for all things parallel software development, from weekly thought
leadership blogs to news, videos, case studies, tutorials and more. Take a
look and join the conversation now. http://goparallel.sourceforge.net/
_______________________________________________
libusb-devel mailing list
https://lists.sourceforge.net/lists/listinfo/libusb-devel
Jirawat I.
2015-02-12 09:59:53 UTC
Permalink
After called libusb_set_debug(4), here are the debug log:

[ 0.001043] [00000145] libusb: debug [libusb_open] open 1.3
[ 0.001060] [00000145] libusb: debug [usbi_add_pollfd] add fd 11 events 4
[ 0.001072] [00000145] libusb: debug [libusb_claim_interface] interface 0

Got these messages when receive normal packet.
[ 0.001291] [00000145] libusb: debug [submit_iso_transfer] need 1 32k URBs
for transfer
[ 0.001331] [00000145] libusb: debug
[libusb_handle_events_timeout_completed] doing our own event handling
[ 0.001337] [00000145] libusb: debug [handle_events] poll() 4 fds with
timeout in 60000ms
[ 0.001351] [00000146] libusb: debug [linux_udev_event_thread_main] udev
event thread entering.
[ 0.038808] [00000145] libusb: debug [handle_events] poll() returned 1
[ 0.038872] [00000145] libusb: debug [reap_for_handle] urb type=0 status=0
transferred=16
[ 0.038876] [00000145] libusb: debug [handle_iso_completion] handling
completion status 0 of iso urb 1/1
[ 0.038880] [00000145] libusb: debug [handle_iso_completion] last URB in
transfer --> complete!
[ 0.038885] [00000145] libusb: debug [disarm_timerfd]
[ 0.038896] [00000145] libusb: debug [usbi_handle_transfer_completion]
transfer 0x89f640 has callback 0x4010c9

messages when LIBUSB_TRANSFER_ERROR
[ 0.038908] [00000145] libusb: debug [submit_iso_transfer] need 1 32k URBs
for transfer
[ 0.038938] [00000145] libusb: debug
[libusb_handle_events_timeout_completed] doing our own event handling
[ 0.038944] [00000145] libusb: debug [handle_events] poll() 4 fds with
timeout in 60000ms
[ 0.042316] [00000145] libusb: debug [handle_events] poll() returned 1
[ 0.042338] [00000145] libusb: debug [reap_for_handle] urb type=0 status=0
transferred=0
[ 0.042341] [00000145] libusb: debug [handle_iso_completion] handling
completion status 0 of iso urb 1/1
[ 0.042344] [00000145] libusb: debug [handle_iso_completion] low-level USB
error -18
[ 0.042346] [00000145] libusb: debug [handle_iso_completion] last URB in
transfer --> complete!
[ 0.042350] [00000145] libusb: debug [disarm_timerfd]

please tell me more, if you want more info.

Best Regrads,
Jirawat I.
Alan Stern
2015-02-12 15:08:08 UTC
Permalink
Post by Jirawat I.
[ 0.001043] [00000145] libusb: debug [libusb_open] open 1.3
[ 0.001060] [00000145] libusb: debug [usbi_add_pollfd] add fd 11 events 4
[ 0.001072] [00000145] libusb: debug [libusb_claim_interface] interface 0
Got these messages when receive normal packet.
[ 0.001291] [00000145] libusb: debug [submit_iso_transfer] need 1 32k URBs
for transfer
[ 0.001331] [00000145] libusb: debug
[libusb_handle_events_timeout_completed] doing our own event handling
[ 0.001337] [00000145] libusb: debug [handle_events] poll() 4 fds with
timeout in 60000ms
[ 0.001351] [00000146] libusb: debug [linux_udev_event_thread_main] udev
event thread entering.
[ 0.038808] [00000145] libusb: debug [handle_events] poll() returned 1
[ 0.038872] [00000145] libusb: debug [reap_for_handle] urb type=0 status=0
transferred=16
[ 0.038876] [00000145] libusb: debug [handle_iso_completion] handling
completion status 0 of iso urb 1/1
[ 0.038880] [00000145] libusb: debug [handle_iso_completion] last URB in
transfer --> complete!
[ 0.038885] [00000145] libusb: debug [disarm_timerfd]
[ 0.038896] [00000145] libusb: debug [usbi_handle_transfer_completion]
transfer 0x89f640 has callback 0x4010c9
messages when LIBUSB_TRANSFER_ERROR
[ 0.038908] [00000145] libusb: debug [submit_iso_transfer] need 1 32k URBs
for transfer
[ 0.038938] [00000145] libusb: debug
[libusb_handle_events_timeout_completed] doing our own event handling
[ 0.038944] [00000145] libusb: debug [handle_events] poll() 4 fds with
timeout in 60000ms
[ 0.042316] [00000145] libusb: debug [handle_events] poll() returned 1
[ 0.042338] [00000145] libusb: debug [reap_for_handle] urb type=0 status=0
transferred=0
[ 0.042341] [00000145] libusb: debug [handle_iso_completion] handling
completion status 0 of iso urb 1/1
[ 0.042344] [00000145] libusb: debug [handle_iso_completion] low-level USB
error -18
[ 0.042346] [00000145] libusb: debug [handle_iso_completion] last URB in
transfer --> complete!
[ 0.042350] [00000145] libusb: debug [disarm_timerfd]
please tell me more, if you want more info.
Are you using Linux? In Linux, error code -18 is -EXDEV, which means
the transfer didn't occur for some reason.

Which Linux kernel release are you using? And what type of host
controller?

Alan Stern
Tim Roberts
2015-02-12 17:32:38 UTC
Permalink
Post by Jirawat I.
I used Silabs C8051F380 for a device send the isochronous 16-byte
packet. My host program on ArchLinux can receive the packet normally.
However, after a long running, my host program
return LIBUSB_TRANSFER_ERROR every time my callback function resubmit
the transfer.
How can I deal this problem?
Should I free this problematic transfer and create a new one?
Can you show us your descriptors? Is this a high-speed device or a
full-speed device? Is the device guaranteed to return a packet for
every request? Remember that, unlike bulk transfers, an isochronous
transfer completes after its time slot, whether the device transferred
anything or not. Is it possible the device simply had nothing to send?
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Jirawat I.
2015-02-13 06:34:31 UTC
Permalink
Post by Alan Stern
Are you using Linux? In Linux, error code -18 is -EXDEV, which means
the transfer didn't occur for some reason.
Which Linux kernel release are you using? And what type of host
controller?
Yes. I used Arch Linux 3.18.6-1-ARCH (kernel: 3.18) x84_64.
For host controller, I run ArchLinux (Guest) on Window7 (Host) via
VirtualBox 4.3.20.

this is `lsusb` from Archlinux:

Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Post by Alan Stern
Bus 001 Device 003: ID 10c4:8846 Cygnal Integrated Products, Inc.
Bus 001 Device 002: ID 80ee:0021 VirtualBox USB Tablet
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
and from Window7

001.003 05c6:9205 Unknown (Qualcomm, Inc.)
Post by Alan Stern
Protocol: (Defined at Interface level)
--------------
Interface 00 Setup 00
Vendor Specific Class (Vendor Specific Subclass) Vendor Specific
Protocol
Endpoint 1 IN interrupt - unsynchronized data [64 0]
Endpoint 2 IN bulk - unsynchronized data [512 0]
Endpoint 1 OUT bulk - unsynchronized data [512 0]
--------------
Interface 01 Setup 00
Vendor Specific Class (Vendor Specific Subclass) Vendor Specific
Protocol
Endpoint 3 IN bulk - unsynchronized data [512 0]
Endpoint 2 OUT bulk - unsynchronized data [512 0]
--------------
Interface 02 Setup 00
Vendor Specific Class (Vendor Specific Subclass) Vendor Specific
Protocol
Endpoint 0 IN interrupt - unsynchronized data [64 0]
Endpoint 1 IN bulk - unsynchronized data [512 0]
Endpoint 3 OUT bulk - unsynchronized data [512 0]
--------------
Interface 03 Setup 00
Vendor Specific Class (Vendor Specific Subclass) Vendor Specific
Protocol
Endpoint 2 IN bulk - unsynchronized data [512 0]
Endpoint 0 OUT bulk - unsynchronized data [512 0]
--------------
002.003 17ef:480f Integrated Webcam [R5U877] (Lenovo)
Protocol: Miscellaneous Device (?) Interface Association
--------------
Interface 00 Setup 00
Video (Video Control)
Endpoint 1 IN interrupt - unsynchronized data [16 0]
--------------
Interface 01 Setup 00
Video (Video Streaming)
Interface 01 Setup 01
Video (Video Streaming)
Endpoint 2 IN isochronous - asynchronous data [3016 0]
Interface 01 Setup 02
Video (Video Streaming)
Endpoint 2 IN isochronous - asynchronous data [5100 0]
Interface 01 Setup 03
Video (Video Streaming)
Endpoint 2 IN isochronous - asynchronous data [5116 0]
Interface 01 Setup 04
Video (Video Streaming)
Endpoint 2 IN isochronous - asynchronous data [5120 0]
--------------
001.002 8087:0020 Integrated Rate Matching Hub (Intel Corp.)
Protocol: Hub (Unused) Single TT
--------------
Interface 00 Setup 00
Hub (Unused) Full speed (or root) hub
Endpoint 1 IN interrupt - unsynchronized data [2 0]
--------------
002.002 8087:0020 Integrated Rate Matching Hub (Intel Corp.)
Protocol: Hub (Unused) Single TT
--------------
Interface 00 Setup 00
Hub (Unused) Full speed (or root) hub
Endpoint 1 IN interrupt - unsynchronized data [1 0]
--------------
001.004 10c4:8846 Unknown (Cygnal Integrated Products, Inc.)
Protocol: (Defined at Interface level)
--------------
Interface 00 Setup 00
Vendor Specific Class
Endpoint 1 IN interrupt - unsynchronized data [8 0]
Endpoint 1 OUT interrupt - unsynchronized data [8 0]
Endpoint 3 IN isochronous - unsynchronized data [16 0]
--------------
Note: *8087:0020* Intel(R) 5 Series/3400 Series Chipset Family USB Enhanced
Host Controller
Post by Alan Stern
Can you show us your descriptors? Is this a high-speed device or a
full-speed device? Is the device guaranteed to return a packet for
every request? Remember that, unlike bulk transfers, an isochronous
transfer completes after its time slot, whether the device transferred
anything or not. Is it possible the device simply had nothing to send?
*Current Configuration* 1 *Speed* Full (12 Mbit/s) *Device Address* 3 *Number
Of Open Pipes* 3

*Device Descriptor USB Temperature Sensor* Offset Field Size Value
Description 0 bLength 1 12h 1 bDescriptorType 1 01h Device 2 bcdUSB 2
0110h USB
Spec 1.1 4 bDeviceClass 1 00h Class info in Ifc Descriptors 5
bDeviceSubClass 1 00h 6 bDeviceProtocol 1 00h 7 bMaxPacketSize0 1 40h 64
bytes 8 idVendor 2 10C4h Cygnal Integrated Products, Inc. 10 idProduct 2
8846h 12 bcdDevice 2 0000h 0.00 14 iManufacturer 1 01h "Silicon
Laboratories Inc." 15 iProduct 1 02h "USB Temperature Sensor" 16
iSerialNumber 1 00h 17 bNumConfigurations 1 01h

*Configuration Descriptor 1 Bus Powered, 40 mA* Offset Field Size Value
Description 0 bLength 1 09h 1 bDescriptorType 1 02h Configuration 2
wTotalLength 2 0027h 4 bNumInterfaces 1 01h 5 bConfigurationValue 1 01h 6
iConfiguration 1 00h 7 bmAttributes 1 80h Bus Powered 4..0: Reserved
...00000 5: Remote Wakeup ..0..... No 6: Self Powered .0...... No, Bus
Powered 7: Reserved (set to one)
(bus-powered for 1.0) 1....... 8 bMaxPower 1 14h 40 mA

*Interface Descriptor 0/0 Vendor-Specific, 3 Endpoints* Offset Field Size
Value Description 0 bLength 1 09h 1 bDescriptorType 1 04h Interface 2
bInterfaceNumber 1 00h 3 bAlternateSetting 1 00h 4 bNumEndpoints 1 03h 5
bInterfaceClass 1 FFh Vendor-Specific 6 bInterfaceSubClass 1 00h 7
bInterfaceProtocol 1 00h 8 iInterface 1 00h

*Endpoint Descriptor 81 1 In, Interrupt, 10 ms* Offset Field Size Value
Description 0 bLength 1 07h 1 bDescriptorType 1 05h Endpoint 2
bEndpointAddress 1 81h 1 In 3 bmAttributes 1 03h Interrupt 1..0: Transfer
Type ......11 Interrupt 7..2: Reserved 000000.. 4 wMaxPacketSize 2 0008h 8
bytes 6 bInterval 1 0Ah 10 ms

*Endpoint Descriptor 01 1 Out, Interrupt, 10 ms* Offset Field Size Value
Description 0 bLength 1 07h 1 bDescriptorType 1 05h Endpoint 2
bEndpointAddress 1 01h 1 Out 3 bmAttributes 1 03h Interrupt 1..0: Transfer
Type ......11 Interrupt 7..2: Reserved 000000.. 4 wMaxPacketSize 2 0008h 8
bytes 6 bInterval 1 0Ah 10 ms

*Endpoint Descriptor 83 3 In, Isochronous, 1 ms* Offset Field Size Value
Description 0 bLength 1 07h 1 bDescriptorType 1 05h Endpoint 2
bEndpointAddress 1 83h 3 In 3 bmAttributes 1 01h Isochronous, No Sync,
Data 1..0:
Transfer Type ......01 Isochronous 7..2: Reserved 000000.. 4
wMaxPacketSize 2 0010h 16 bytes 6 bInterval 1 01h 1 ms
I received temperature from ADC and sent via endpoint 0x83
I loaded ADC-sampled data into USB transceiver FIFO in SET_CONFIGURATION
state
and every time USB transceiver interrupted "already sent" for IN DATA,
I loaded the next sampled data into FIFO waited for next IN request.

Is it possible the device had nothing to send in sometime because of this?
If there is any buggy with this, Could you tell me the right way?

Thank you,
Jirawat I.
Tim Roberts
2015-02-13 18:34:05 UTC
Permalink
Post by Jirawat I.
I received temperature from ADC and sent via endpoint 0x83
I loaded ADC-sampled data into USB transceiver FIFO in
SET_CONFIGURATION state
and every time USB transceiver interrupted "already sent" for IN DATA,
I loaded the next sampled data into FIFO waited for next IN request.
Is it possible the device had nothing to send in sometime because of this?
Hard to say. It depends on the timing. Why did you choose an
isochronous pipe? There are very, very, very few legitimate uses for
isochronous pipes, and this does not seem like one of them. Why not
just use an interrupt pipe? That way, you get the reserved bandwidth
slot without the vagueries of isochronous packet handling.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Jirawat I.
2015-02-13 21:42:41 UTC
Permalink
Post by Tim Roberts
Hard to say. It depends on the timing. Why did you choose an
isochronous pipe? There are very, very, very few legitimate uses for
isochronous pipes, and this does not seem like one of them. Why not
just use an interrupt pipe? That way, you get the reserved bandwidth
slot without the vagueries of isochronous packet handling.
I thought that isochronous is suitable for streaming audio and video, and
may be for DAQ.
I didn't try interrupt pipe at the first time because I didn't sure the
guaranteed speed of 64KB/s/ per pipe.
Post by Tim Roberts
It might be a good idea to try running your program on a real computer
instead of a virtual machine. Sometimes that can make a difference.
As you and Mr. Tim Roberts suggest, I'm going to test on real computer. and
if there is a problem, I will change to the interrupt pipe.
However, at the end, the system will be run on the ARM-based Linux (like
Raspberry Pi), and now it struck with isochronous pipe too. I heard that
the RPi is so buggy about isochronous.
Maybe I should start again with common interrupt pipe.

Thank for your kindness
Jirawat I.
Tim Roberts
2015-02-13 22:11:50 UTC
Permalink
Post by Tim Roberts
Hard to say. It depends on the timing. Why did you choose an
isochronous pipe? There are very, very, very few legitimate uses for
isochronous pipes, and this does not seem like one of them. Why not
just use an interrupt pipe? That way, you get the reserved bandwidth
slot without the vagueries of isochronous packet handling.
I thought that isochronous is suitable for streaming audio and video,
and may be for DAQ.
With bulk and interrupt pipes, if a packet is damaged in transit, it
gets retried automatically by the hardware. With an isochronous pipe,
if a packet is damaged in transit, the packet is lost. The driver is
told about the loss, but the data is gone.

Plus, with bulk and interrupt, if the hardware skips a couple of
intervals, your request remains outstanding until it is satisfied. With
isochronous, your request is finished as soon as its scheduled interval
arrives, whether anything was transferred or not. That's usually not
very convenient.

Thus, isochronous is suitable for those limited cases where your data is
so fast that you can't ever afford the delay from a potential retry, and
where the loss of a packet is no big deal. That pretty much limits you
to audio and video.
Post by Tim Roberts
I didn't try interrupt pipe at the first time because I didn't sure
the guaranteed speed of 64KB/s/ per pipe.
I'm not sure what you're trying to say. Your isochronous pipe is
currently set up for 16 bytes per frame. That's 16kB/s. Interrupt, as
you say, can handle 64kB/s. Even a bulk pipe would probably work for
you, but isochronous is almost always the wrong choice.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Alan Stern
2015-02-13 15:04:16 UTC
Permalink
Post by Jirawat I.
Post by Alan Stern
Are you using Linux? In Linux, error code -18 is -EXDEV, which means
the transfer didn't occur for some reason.
Which Linux kernel release are you using? And what type of host
controller?
Yes. I used Arch Linux 3.18.6-1-ARCH (kernel: 3.18) x84_64.
For host controller, I run ArchLinux (Guest) on Window7 (Host) via
VirtualBox 4.3.20.
Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Post by Alan Stern
Bus 001 Device 003: ID 10c4:8846 Cygnal Integrated Products, Inc.
Bus 001 Device 002: ID 80ee:0021 VirtualBox USB Tablet
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
It might be a good idea to try running your program on a real computer
instead of a virtual machine. Sometimes that can make a difference.

Alan Stern
Loading...