In their documentation, they suggest you to read the usb2 specifications first: Here, it really helps you understand how things work here.
Installation of Libusb
You have to obtain the source code from Their Website and build it yourself. Or if your Distribution's repository contains the package, you can easily install it from there.
---
If you have setup the library, go on...
Communication
Communication between devices and client software is conceptualized as using pipes. Each pipe is a communication channel between software on the host and an endpoint on a device. Each endpoint represents a part of a device that fulfills one specific purpose for that device, such as to receive commands or transmit data. A full speed device can have up to 16 endpoints, though low speed devices can have only three.
All USB devices support endpoint 0 when powered up. This endpoint is the target of the default pipe. After the attachment of a device has been detected, the USBD software uses endpoint 0 to initialise the device, perform generic (i.e. non device-specific) configuration, and obtain information about the other endpoints provided by the device. Endpoints are characterised by their endpoint number (set at design time) and bus bandwidth, access frequency, latency and error handling behaviour requirements.
Once the endpoints of a device have been identified and configured, pipes come into existence allowing the client software to communicate with the device. A pipe has associated with it characteristics such as a claim on bus access and bandwidth, the type of transfer, the direction of transfer and the maximum data payload size.
USB defines four types of transfer: control transfers which are typically used for command or status operations, interrupt transfers which are initiated by a device to request some action from the host, isochronous transfers which are used to carry data the delivery of which is time critical (such as for video and speech), and bulk transfers which can use all available bandwidth but are not time critical. All transfers take the form of packets, which contain control information, data and error checking fields.
There are also two types of pipe: message pipes and stream pipes. Control transfers are made using message pipes. In a message pipe, the data portion of each packet has some meaning to the USB system software.
Stream pipes are used for interrupt, isochronous and bulk transfers. In a stream pipe, the data portion of the packet has no defined meaning to the USB: the data is merely conveyed between client software and device.
Synchronous Interface
The synchronous I/O interface allows you to perform a USB transfer with a single function call. When the function call returns, the transfer has completed and you can parse the results. The main advantage of this model is simplicity: you did everything with a single simple function call.
However, this interface has its limitations. Your application will sleep inside libusb_bulk_transfer()(when using bulk transfer) until the transaction has completed. If it takes 3 hours, your application will be sleeping for that long. Execution will be tied up inside the library; the entire thread will be useless for that duration.
Another issue is that by tieing up the thread with that single transaction there is no possibility of performing I/O with multiple endpoints and/or multiple devices simultaneously, unless you resort to creating one thread per transaction.
Additionally, there is no opportunity to cancel the transfer after the request has been submitted.
Devices and interfaces
Each usb device is manipulated with a libusb_device and libusb_device_handle objects in libusb. The libusb API ties an open device to a specific interface. This means that if you want to claim multiple interfaces on a device, you should open the device multiple times to receive one libusb_dev_handle for each interface you want to communicate with. Don't forget to call usb_claim_interface.
What does this mean? Means you have to claim the interface before you do any operation on the device, and also, you have to release the claimed interface after you are finished with the device.
OK, now what? yup, we have to find these, so called devices/interfaces so that we can claim them and assign to a handle and so on... here is the magic...

Each device has it's own configuration values, like vendor id, product id, etc. We use these settings to discover the desired device and work with. First we have to write a function to determine these options and print them, so that we can discover the right one; the basic operations we have to do are:
- initialize the library by calling the function libusb_init and creating a session
- Call the function libusb_get_device_list to get a list of connected devices. This creates an array of libusb_device containing all usb devices connected to the system.
- Loop through all these devices and check their options
- Discover the one and open the device either by libusb_open or libusb_open_device_with_vid_pid(when you know vendor and product id of the device) to open the device
- Clear the list you got from libusb_get_device_list by using libusb_free_device_list
- Claim the interface with libusb_claim_interface (requires you to know the interface numbers of device)
- Do desired I/O
- Release the device by using libusb_release_interface
- Close the device you openedbefore, by using libusb_close
- Close the session by using libusb_exit
#include <iostream> #include <libusb.h> using namespace std; void printdev(libusb_device *dev); //prototype of the function int main() { libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices 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 a library session 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 } cout<<cnt<<" Devices in list."<<endl; //print total number of usb devices ssize_t i; //for iterating through the list for(i = 0; i < cnt; i++) { printdev(devs[i]); //print specs of this device } libusb_free_device_list(devs, 1); //free the list, unref the devices in it libusb_exit(ctx); //close the session return 0; } void printdev(libusb_device *dev) { libusb_device_descriptor desc; int r = libusb_get_device_descriptor(dev, &desc); if (r < 0) { cout<<"failed to get device descriptor"<<endl; return; } cout<<"Number of possible configurations: "<<(int)desc.bNumConfigurations<<" "; cout<<"Device Class: "<<(int)desc.bDeviceClass<<" "; cout<<"VendorID: "<<desc.idVendor<<" "; cout<<"ProductID: "<<desc.idProduct<<endl; libusb_config_descriptor *config; libusb_get_config_descriptor(dev, 0, &config); cout<<"Interfaces: "<<(int)config->bNumInterfaces<<" ||| "; const libusb_interface *inter; const libusb_interface_descriptor *interdesc; const libusb_endpoint_descriptor *epdesc; for(int i=0; i<(int)config->bNumInterfaces; i++) { inter = &config->interface[i]; cout<<"Number of alternate settings: "<<inter->num_altsetting<<" | "; for(int j=0; j<inter->num_altsetting; j++) { interdesc = &inter->altsetting[j]; cout<<"Interface Number: "<<(int)interdesc->bInterfaceNumber<<" | "; cout<<"Number of endpoints: "<<(int)interdesc->bNumEndpoints<<" | "; for(int k=0; k<(int)interdesc->bNumEndpoints; k++) { epdesc = &interdesc->endpoint[k]; cout<<"Descriptor Type: "<<(int)epdesc->bDescriptorType<<" | "; cout<<"EP Address: "<<(int)epdesc->bEndpointAddress<<" | "; } } } cout<<endl<<endl<<endl; libusb_free_config_descriptor(config); }
OK, now compile it and try to see things... I ran this program and checked the devices, then connected my pendrive and ran the program again... there was a new entry up there, this way I could find the vendor id and product id of that pendrive so that I can open it.
**Note** Device discovery (calling libusb_get_device_list()) returns a freshly-allocated list of devices. The list itself must be freed when you are done with it. libusb also needs to know when it is OK to free the contents of the list; the devices themselves.
To handle these issues, libusb provides you with two separate items:
- A function to free the list itself
- A reference counting system for the devices inside
With the above information in mind, the process of opening a device can be viewed as follows:
- Discover devices using libusb_get_device_list().
- Choose the device that you want to operate, and call libusb_open().
- Unref all devices in the discovered device list.
- Free the discovered device list.
For convenience, the libusb_free_device_list() function includes a parameter to optionally unreference all the devices in the list before freeing the list itself. This combines steps 3 and 4 above.
OK, here is the libusb1's API documentationreference on functions if you need

OK, now you can find your desired devices... it's the time to open this device, claim it and perform a very simple I/O.
If you have the vendor and product id, use libusb_open_device_with_vid_pid.
Also note that, if kernel (your OS) connects to the device, you can't claim it. In this case you have to call libusb_detach_kernel_driver to detach kernel from your device. If you want to know whether the kernel did this or not, use libusb_kernel_driver_active, if the return value is 1, then kernel attached a driver to your device.
Bulk Transfer
To do a bulk transfer to your device, you have to have a device handler for your usb device, and you have to know which endpoint to use (get from device specs above).
Refer Here for information on the syntax.
Now, here's an example to combine all the things I mentioned above:
#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; }
Conclusion: this tutorial is just a simple introduction to the subject... practice with other synchronous transfers, then move on to the asynchronous... See? there is much to learn

Hope this was helpful to get you started
