Discussion:
[libusb] Losing bytes libusb
Aurquiel ---
2017-03-01 14:02:54 UTC
Permalink
I have receiving data form an interrupt transfer, i have to receive packets of 204 bytes but after the first package one byte is lost, using a 1024 bytes of transfer.


For example


In one transmission of 1024 bytes i receive packets of 204 bytes inside, so in the first four packets it will fill 816 bytes of the 1024 bytes, the next transmission will have to split the packets 208 bytes in the first transmission ant the rest 8 bytes in the next one followed for the rest, but when they split always i lost one byte in the junction of the two packets.


Code c++ i write:


unsigned char *MPEG2_TS=new unsigned char[1024];
unsigned char *MPEG2_TS_2=new unsigned char[1024];


//It's a return of libusb_interrupt_transfer with the number of bytes that were transferred
int transferred=0;


//It's a return of libusb_interrupt_transfer return 0 if the transfer was successful
int result=0;


//Receiving Transfer


result=libusb_interrupt_transfer (device_handle, //The device handle
0x82, //Endponit 2
MPEG2_TS, //Buffer
1024, //Size of Buffer
&transferred, //Return the number of bytes transferred
0 //waiting time to receive the answer
);


result=libusb_interrupt_transfer (device_handle, //The device handle
0x82, //Endponit 2
MPEG2_TS_2, //Buffer
1024, //Size of Buffer
&transferred, //Return the number of bytes transferred
0 //waiting time to receive the answer
);

write_to_file_2(MPEG2_TS);
write_to_file(MPEG2_TS_2);

I write the code of transmission twice to see what is happening i just receive 2048 bytes and writing to a file, i will use a while loop with one transfer if a resolve the issue.

My device is always sending data through the USB i just wanna catch the packets and join them. i don't know if executing twice the libusb receive interrupt transfer is too slow and my packets are losing
Tim Roberts
2017-03-01 18:28:29 UTC
Permalink
Post by Aurquiel ---
I have receiving data form an interrupt transfer, i have to receive
packets of 204 bytes but after the first package one byte is lost,
using a 1024 bytes of transfer.
For example
In one transmission of 1024 bytes i receive packets of 204 bytes
inside, so in the first four packets it will fill 816 bytes of the
1024 bytes, the next transmission will have to split the packets 208
bytes in the first transmission ant the rest 8 bytes in the next one
followed for the rest, but when they split always i lost one byte in
the junction of the two packets.
...
I write the code of transmission twice to see what is happening i just
receive 2048 bytes and writing to a file, i will use a while loop with
one transfer if a resolve the issue.
My device is always sending data through the USB i just wanna catch
the packets and join them. i don't know if executing twice the libusb
receive interrupt transfer is too slow and my packets are losing
You need to look at the code in your device. If you are actually
receiving a full 1024-byte packet in your app, then that means the
maximum packet size for the interrupt endpoint must be 1024 bytes. That
means the packing of the packets is occurring in the device. That is,
the device is just cramming the 204-byte TS packets into its FIFO. Once
it has 1024 bytes, it can respond to the read request from the host.,
which should leave 4 bytes in the FIFO. After it gets 5 more TS
packets, it can respond to the next read request, leaving 8 bytes in the
FIFO. Libusb isn't involved in that.

How large is the FIFO? You are using synchronous transfers, which means
you wait until the first transfer is complete before you submit
another. USB does not allow a device to send unless there is a read
request waiting, so in between your transfers, there is a gap where your
device cannot respond. If your FIFO is not large enough to carry
through, you will lose data.
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Aurquiel ---
2017-03-02 12:20:43 UTC
Permalink
Post by Tim Roberts
You need to look at the code in your device. If you are actually
receiving a full 1024-byte packet in your app, then that means the
maximum packet size for the interrupt endpoint must be 1024 bytes. That
means the packing of the packets is occurring in the device. That is,
the device is just cramming the 204-byte TS packets into its FIFO. Once
it has 1024 bytes, it can respond to the read request from the host.,
which should leave 4 bytes in the FIFO. After it gets 5 more TS
packets, it can respond to the next read request, leaving 8 bytes in the
FIFO. Libusb isn't involved in that.
How large is the FIFO? You are using synchronous transfers, which means
you wait until the first transfer is complete before you submit
another. USB does not allow a device to send unless there is a read
request waiting, so in between your transfers, there is a gap where your
device cannot respond. If your FIFO is not large enough to carry
through, you will lose data.
--
Providenza & Boekelheide, Inc.
Here is the output information of my usb device


Bus 003 Device 013: ID 04b4:1004 Cypress Semiconductor Corp.

Device Descriptor:

bLength 18

bDescriptorType 1

bcdUSB 2.00

bDeviceClass 0 (Defined at Interface level)

bDeviceSubClass 0

bDeviceProtocol 0

bMaxPacketSize0 64

idVendor 0x04b4 Cypress Semiconductor Corp.

idProduct 0x1004

bcdDevice 0.00

iManufacturer 1 Cypress

iProduct 2 DMB-TV

iSerial 0

bNumConfigurations 1

Configuration Descriptor:

bLength 9

bDescriptorType 2

wTotalLength 25

bNumInterfaces 1

bConfigurationValue 1

iConfiguration 0

bmAttributes 0x80

(Bus Powered)

MaxPower 100mA

Interface Descriptor:

bLength 9

bDescriptorType 4

bInterfaceNumber 0

bAlternateSetting 0

bNumEndpoints 1

bInterfaceClass 255 Vendor Specific Class

bInterfaceSubClass 0

bInterfaceProtocol 0

iInterface 0

Endpoint Descriptor:

bLength 7

bDescriptorType 5

bEndpointAddress 0x82 EP 2 IN

bmAttributes 3

Transfer Type Interrupt

Synch Type None

Usage Type Data

wMaxPacketSize 0x0400 1x 1024 bytes

bInterval 1

Device Qualifier (for other device speed):

bLength 10

bDescriptorType 6

bcdUSB 2.00

bDeviceClass 0 (Defined at Interface level)

bDeviceSubClass 0

bDeviceProtocol 0

bMaxPacketSize0 64

bNumConfigurations 1

Device Status: 0x0000

(Bus Powered)


My FIFO is in mode when he fills will send the data automatically. I am using a quad buffer configuration, the maximum i can reach in the device, but it seems the recepcion and the sending happen so fast for a synchronous transfer.

I write another code using an asynchronus transfer type, i do not modified the firmware,but the buffer remians empty, here the code (complete)

This part it's already done, open and claimthe device
------------------------------------------------------------------------------------------------------------------
#ifndef USB_H_INCLUDED
#define USB_H_INCLUDED

#include <libusb-1.0/libusb.h>

libusb_device_handle *device_handle; //For device handle, for that devicie
libusb_context *ctx=NULL; //the context when a libusb's session star
unsigned int error; //error register

void usb_conecction()
{
libusb_device **list=NULL; //pointer to the pointer of the devices
error=0; //variable look any error of conecction zero means no error
int r; //for return values
ssize_t number_of_devices; //holding number of devices in list

r = libusb_init(&ctx); //initialize a library session
//If r less than zero error
if(r < 0)
{
//"Error library inicialization"
error=1; //"For 1 Error library inicialization";
}

libusb_set_debug(ctx, 5); //set verbosity level to 3, as suggested in the documentation, this function activate the debug of libusb increase the int parameter to see more debug advices

number_of_devices = libusb_get_device_list(ctx,&list); //get a list of device fil dev[] struct

//open device, with in decimal way idvendor=1204 idproduct=4100
device_handle=libusb_open_device_with_vid_pid(ctx,1204,4100);

//If can not open device set error status, can't get a device handle
if((device_handle == NULL)||(number_of_devices==0))
{
//Free the device list
libusb_free_device_list(list,1);
//"Cannot open device"
error=2; //"For 2 Error Can not open device";
}else //if the device could be opened
{
//Free the device list
libusb_free_device_list(list,1);

//looking if the kernel attached the driver
//If The kernel driver is attached
if(libusb_kernel_driver_active(device_handle, 0) == 1)
{
//Deattach the kernel driver
libusb_detach_kernel_driver(device_handle,1);
}

//Claim interface 0 (the first) of device (the usb device had just 1)
int claim_status = libusb_claim_interface(device_handle, 0);

//If claim_status less than 0 couldn't claim the device
if(claim_status < 0)
{
//"Cannot claim the device"
error=3; //"For 3 Error Can not claim the device";
}

} //End of else

} //End of function

void usb_disconecction()
{
//release the claimed interface
int status_release=libusb_release_interface(device_handle, 0);

//if cannot be released
if (status_release!=0)
{
//"Can not release device"
error=4; //"For 4 Error Can not release device";
}

//Close the device we opened
libusb_close(device_handle);
//Exit the session
libusb_exit(ctx);

}

#endif // USB_H_INCLUDED
-----------------------------------------------------------------------------------------------------------------

This is the part for the asynchronus transfer

---------*****************************++************---------------------------------------------

#ifndef THREAD_H_INCLUDED
#define THREAD_H_INCLUDED

#include "usb.h" //For device_handle
#include "samsung.h" //For delay function
#include <thread>
#include <iostream>
#include <fstream>

static void read_callback(struct libusb_transfer *transfer);
static struct libusb_transfer *create_transfer (libusb_device_handle *handle,size_t length);
void write_to_file(unsigned char *p);
void loop();
std::ofstream outfile ("data.ts"); //archieve


static void read_callback(struct libusb_transfer *transfer)
{
int res;
if(transfer->status ==LIBUSB_TRANSFER_COMPLETED)
{
/* Success! Handle data received */
}
else
{
printf("Error: %d\n",transfer->status);
}
/* Re-submit the transfer object. */
res = libusb_submit_transfer(transfer);

if(res !=0)
{
printf("submitting. error code: %d\n", res);
}
}

static struct libusb_transfer *create_transfer (libusb_device_handle *handle,size_t length)
{
struct libusb_transfer *transfer;

unsigned char *MPEG2_TS=new unsigned char[length];

transfer = libusb_alloc_transfer(0);

libusb_fill_interrupt_transfer(transfer,
device_handle,
0x82,
MPEG2_TS,
length,
read_callback,
NULL,
0
);

write_to_file(MPEG2_TS); //this part is for checking if sometinhg is receiving

return transfer;
}



void loop()
{
for(int i=0;i<10;i++)
{
struct libusb_transfer *transfer = create_transfer(device_handle, 1024);
libusb_submit_transfer(transfer);
}

}


void write_to_file(unsigned char *p)
{

for (int i=0; i<1024-1;i++)
{
outfile<<p[i];
}

}


#endif // THREAD_H_INCLUDED



I don't know why the buffer just fills with zeros 0000000000 the file just fills with zeros
Aurquiel ---
2017-03-03 15:51:34 UTC
Permalink
I changed the way to get the packets now i am using an asynchronuos transfer for queue transfers, i don't know what it's happening if it's too slow to write the file or if something more else.

Information of interest about the endpoint:

Endpoint Descriptor:
bLength 7
bDescriptorType 5
bEndpointAddress 0x82 EP 2 IN
bmAttributes 3
Transfer Type Interrupt
Synch Type None
Usage Type Data
wMaxPacketSize 0x0400 1x 1024 bytes
bInterval 1

I just have one endpint to receive data, i am not sending anything back.

In mthe callback function i send a pointer to the buffer to a function that write the buffer to a file

static void read_callback(struct libusb_transfer *transfer)
{
int res;
if(transfer->status ==LIBUSB_TRANSFER_COMPLETED)
{
/* Success! Handle data received */
}
else
{
printf("Error: %d\n",transfer->status);
}
/* Re-submit the transfer object. */

res = libusb_submit_transfer(transfer);

write_to_file(transfer->buffer);

if(res !=0)
{
printf("submitting. error code: %d\n", res);
}
}


I think is too slow for the writing, if soo how to get the buffer information??? beacuse the buffer is always requeue.

The function to fill

static struct libusb_transfer *create_transfer (libusb_device_handle *handle,size_t length)
{
struct libusb_transfer *transfer;

unsigned char *MPEG2_TS=new unsigned char[length];

transfer = libusb_alloc_transfer(0);

libusb_fill_bulk_transfer(transfer,
device_handle,
0x82,
MPEG2_TS,
length,
read_callback,
NULL,
0
);


return transfer;
}

the function to set the requeue packets and handle

void loop()
{
for(int i=0;i<2000;i++)
{
struct libusb_transfer *transfer = create_transfer(device_handle, 1024);
libusb_submit_transfer(transfer);
}

int res;
/* Handle Events */
while(1)
{
res =libusb_handle_events(ctx);

if(res <0)
{
std::cout<<"handle_events()error"<<res<<std::endl;
/* Break out of this loop only on fatal error.*/

if( (res != LIBUSB_ERROR_BUSY) && (res != LIBUSB_ERROR_TIMEOUT) && (res!= LIBUSB_ERROR_OVERFLOW) && (res!=LIBUSB_ERROR_INTERRUPTED))
{
break;
}

}
}
}

The function to write to a file

void write_to_file(unsigned char *p)
{

for (int i=0; i<1024-1;i++)
{
outfile<<p[i];
}

}

But in the file i am see that i am loosing packets, because i must recive packtes of 204 bytes inside packtes of 1024 bytes
Tim Roberts
2017-03-03 20:33:35 UTC
Permalink
Post by Aurquiel ---
The function to write to a file
void write_to_file(unsigned char *p)
{
for (int i=0; i<1024-1;i++)
{
outfile<<p[i];
}
}
But in the file i am see that i am loosing packets, because i must
recive packtes of 204 bytes inside packtes of 1024 bytes
You are losing a byte at the packet boundaries because you are only
writing 1023 bytes to the file. Your "for" loop is wrong.

I suggest you replace that whole function with
outfile.write( (char *)p, 1024 );
--
Tim Roberts, ***@probo.com
Providenza & Boekelheide, Inc.
Loading...