Swathi Sham
Swathi Sham

Reputation: 51

Not able to transfer data through libusb

I am trying to run this program for sending data using libusb. I am not able to find the endpoint of my USB port. This parameter is required in the libusb_bulk_transfer function.

#include <iostream>
#include <libusb.h>

using namespace std;

int main() {
    libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
    libusb_device_handle *dev_handle; //a device handle
    libusb_context *ctx = NULL; //a libusb session
    int r; //for return values
    ssize_t cnt; //holding number of devices in list
    r = libusb_init(&ctx); //initialize the library for the session we just declared
    if(r < 0) {
        cout<<"Init Error "<<r<<endl; //there was an error
        return 1;
    }
    libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation

    cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
    if(cnt < 0) {
        cout<<"Get Device Error"<<endl; //there was an error
        return 1;
    }
    cout<<cnt<<" Devices in list."<<endl;

    dev_handle = libusb_open_device_with_vid_pid(ctx, 5118, 7424); //these are vendorID and productID I found for my usb device
    if(dev_handle == NULL)
        cout<<"Cannot open device"<<endl;
    else
        cout<<"Device Opened"<<endl;
    libusb_free_device_list(devs, 1); //free the list, unref the devices in it

    unsigned char *data = new unsigned char[4]; //data to write
    data[0]='a';data[1]='b';data[2]='c';data[3]='d'; //some dummy values

    int actual; //used to find out how many bytes were written
    if(libusb_kernel_driver_active(dev_handle, 0) == 1) { //find out if kernel driver is attached
        cout<<"Kernel Driver Active"<<endl;
        if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it
            cout<<"Kernel Driver Detached!"<<endl;
    }
    r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device (mine had jsut 1)
    if(r < 0) {
        cout<<"Cannot Claim Interface"<<endl;
        return 1;
    }
    cout<<"Claimed Interface"<<endl;

    cout<<"Data->"<<data<<"<-"<<endl; //just to see the data we want to write : abcd
    cout<<"Writing Data..."<<endl;
    r = libusb_bulk_transfer(dev_handle, (2 | LIBUSB_ENDPOINT_OUT), data, 4, &actual, 0); //my device's out endpoint was 2, found with trial- the device had 2 endpoints: 2 and 129
    if(r == 0 && actual == 4) //we wrote the 4 bytes successfully
        cout<<"Writing Successful!"<<endl;
    else
        cout<<"Write Error"<<endl;

    r = libusb_release_interface(dev_handle, 0); //release the claimed interface
    if(r!=0) {
        cout<<"Cannot Release Interface"<<endl;
        return 1;
    }
    cout<<"Released Interface"<<endl;

    libusb_close(dev_handle); //close the device we opened
    libusb_exit(ctx); //needs to be called to end the

    delete[] data; //delete the allocated memory for data
    return 0;
}

The following is the program on my host PC to receive the data.

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include <sys/stat.h>
#include <fcntl.h>
void main()
{

read_port();
//return 0;
}


read_port(void)
{
    int fd = open("/dev/ttyACM0", O_RDONLY | O_NOCTTY);
    if (fd == -1)
    {
    /* Could not open the port. */
    perror("open_port: Unable to open /dev/ttyACM0) - ");
    }

    char buffer[32];
    for(;;)
   {
    int n = read(fd, buffer, sizeof(buffer));
   if (n < 0)
      fputs("read failed!\n", stderr);
   printf("\n %d", n);
  }
}

Please help. Thanks in advance.

Upvotes: 1

Views: 2691

Answers (1)

mark sabido
mark sabido

Reputation: 440

In answer to your actual question, if you want to find out what actual endpoints are attached the device, lsusb is your friend

If you are unsure what your device's vendor and device ID are, type:

lsusb

and you will get something like this:

Bus 001 Device 005: ID 093a:2510 Pixart Imaging, Inc. Optical Mouse
Bus 001 Device 015: ID 413c:2003 Dell Computer Corp. Keyboard
Bus 001 Device 020: ID 0483:3748 STMicroelectronics ST-LINK/V2
Bus 001 Device 002: ID 8087:0020 Intel Corp. Integrated Rate Matching Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Let's say we want to know what endpoints are present on the ST-LINK/V2, we use lsusb in verbose mode using the -v option, and specify only the device we're interested in with the -d option with the ID:

lsusb -v -d 0483:3748

We will get a big list of fields from this. The topology is roughly:

device->configuration->interface->endpoints
      |                interface->endpoints
      |                interface->endpoints
      |
      ->configuration->interface->endpoints
                       interface->endpoints
                       ...

So locate the interface you want to use (often 0):

  • locate the interface descriptor

  • encapsulated inside this you can see the endpoint descriptors

  • then look for the term bEndpointAddress to get the actual value

In this case we have a bulk in endpoint with an address of 0x81:

bEndpointAddress     0x81  EP 1 IN

And another a little further down:

bEndpointAddress     0x02  EP 2 OUT

And another in endpoint:

bEndpointAddress     0x83  EP 3 IN

For completeness here is the full dump:

Bus 001 Device 020: ID 0483:3748 STMicroelectronics ST-LINK/V2

Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x0483 STMicroelectronics
  idProduct          0x3748 ST-LINK/V2
  bcdDevice            1.00
  iManufacturer           1 STMicroelectronics
  iProduct                2 STM32 STLink
  iSerial                 3 000000000001
  bNumConfigurations      1
    Configuration Descriptor:
      bLength                 9
      bDescriptorType         2
      wTotalLength           39
      bNumInterfaces          1
      bConfigurationValue     1
      iConfiguration          0 
      bmAttributes         0x80
      (Bus Powered)
      MaxPower              100mA
        Interface Descriptor:
           bLength                 9
           bDescriptorType         4
           bInterfaceNumber        0
           bAlternateSetting       0
           bNumEndpoints           3
           bInterfaceClass       255 Vendor Specific Class
           bInterfaceSubClass    255 Vendor Specific Subclass
           bInterfaceProtocol    255 Vendor Specific Protocol
           iInterface              4 ST Link
             Endpoint Descriptor:
                bLength                 7
                bDescriptorType         5
                bEndpointAddress     0x81  EP 1 IN   *!eg end point address!*
                bmAttributes            2
                Transfer Type            Bulk
                Synch Type               None
                Usage Type               Data
                wMaxPacketSize     0x0040  1x 64 bytes
                bInterval               0
             Endpoint Descriptor:
                bLength                 7
                bDescriptorType         5
                bEndpointAddress     0x02  EP 2 OUT
                bmAttributes            2
                Transfer Type            Bulk
                Synch Type               None
                Usage Type               Data
                wMaxPacketSize     0x0040  1x 64 bytes
                bInterval               0
             Endpoint Descriptor:
                bLength                 7
                bDescriptorType         5
                bEndpointAddress     0x83  EP 3 IN
                bmAttributes            2
                Transfer Type            Bulk
                Synch Type               None
                Usage Type               Data
                wMaxPacketSize     0x0040  1x 64 bytes
                bInterval               0
  Device Status:     0x0000

(Bus Powered)

Upvotes: 3

Related Questions