NOTE: if you read the tutorial and are still experiencing difficulties and would like help, you are asked to start a new topic on the forums.
Please do NOT reply to this thread to ask a technical question. Replies to THIS thread should be corrections and enhancements on the tutorial/howto only.
Thanks in advance for your co-operation.
LinuxForums.org

------------------------------------------


Developing Linux Device Drivers using Libusb Programming Interface


Introduction
We often come across a situation where a USB device which runs perfectly on Windows platform does not even get detected on Linux. Lack of support for USB devices is one of the reason why some people don't embrace Linux. Now there is a new API(APplication Programming Interface )by name Libusb which helps the developers to develop USB device drivers on the fly!

What is Libusb
Libusb is a high-level language API which conceals low-level kernel interactions with the USB modules. It provides a set of function which are adequate to develop a device driver for a USB device from the Userspace.

Libusb is not complex
For any wannabe Linux Kernel programmers developing device driver as a Kernel module is a herculean task. Developing kernel modules requires fair degnee of proficiency in 'C' language and also good idea of kernel subsystems, data structures etc. All these are enough to put-off a developer from venturing into Device Driver programming.Libusb has been designed to address this shortcoming. Simplified interface allows developers to develop USB drivers from the userspace . Libusb library functions provide high level abstraction to the Kernel structures and allows the developers to have access to these structures through the USBFS(USBfilesystem).

Its Cross-platform
Beauty of Libusb lies in its crossplatform functionality. Driver written for one platform could be easily ported onto another platform with little or no changes, currently following operating systems are supported by Libusb.

Linux
FreeBSD
Darwin
OS X

This HOWTO focuses on how Libusb can be used on Linux platform. For information about other platforms goto http://http://libusb.sourceforge.net/.


LIBUSB ON LINUX
Linux is the most popular platform for the Libusb API,the reason being growing popularity of Linux as a stable OS. On Linux Libusb makes of the USBFS file system. by default USBFS is automatically mounted when the system is booted.

What is USBFS ?
USBFS is a filesystem specifically designed for USB devices, by default this filesystem gets mounted when the system is booted and it can be found at /proc/bus/usb/. This filesystem consists of information about all the USB devices that are connected to the computer.Libusb makes use of this filesystem to interact with the USB devices.

Following C program can be a stepping stone into the world of Libusb.This program can be used to gather all the technical/hardware details of a USB device connected to the computer ,ensure that some USB device is connected into the USB port.

Details like Vendor-Id , Product-Id ,Endpoint addresses of a USB device is of paramount importance for a device driver developer.

Code:
/* testlibusb.c */ 

#include 
#include 


void print_endpoint(struct usb_endpoint_descriptor *endpoint) 
{ 
printf(" bEndpointAddress: %02xh\n", endpoint->bEndpointAddress); 
printf(" bmAttributes: %02xh\n", endpoint->bmAttributes); 
printf(" wMaxPacketSize: %d\n", endpoint->wMaxPacketSize); 
printf(" bInterval: %d\n", endpoint->bInterval); 
printf(" bRefresh: %d\n", endpoint->bRefresh); 
printf(" bSynchAddress: %d\n", endpoint->bSynchAddress); 
} 


void print_altsetting(struct usb_interface_descriptor *interface) 
{ 
int i; 

printf(" bInterfaceNumber: %d\n", interface->bInterfaceNumber); 
printf(" bAlternateSetting: %d\n", interface->bAlternateSetting); 
printf(" bNumEndpoints: %d\n", interface->bNumEndpoints); 
printf(" bInterfaceClass: %d\n", interface->bInterfaceClass); 
printf(" bInterfaceSubClass: %d\n", interface->bInterfaceSubClass); 
printf(" bInterfaceProtocol: %d\n", interface->bInterfaceProtocol); 
printf(" iInterface: %d\n", interface->iInterface); 

for &#40;i = 0; i < interface->bNumEndpoints; i++&#41; 
print_endpoint&#40;&interface->endpoint&#91;i&#93;&#41;; 
&#125; 


void print_interface&#40;struct usb_interface *interface&#41; 
&#123; 
int i; 

for &#40;i = 0; i < interface->num_altsetting; i++&#41; 
print_altsetting&#40;&interface->altsetting&#91;i&#93;&#41;; 
&#125; 


void print_configuration&#40;struct usb_config_descriptor *config&#41; 
&#123; 
int i; 

printf&#40;" wTotalLength&#58; %d\n", config->wTotalLength&#41;; 
printf&#40;" bNumInterfaces&#58; %d\n", config->bNumInterfaces&#41;; 
printf&#40;" bConfigurationValue&#58; %d\n", config->bConfigurationValue&#41;; 
printf&#40;" iConfiguration&#58; %d\n", config->iConfiguration&#41;; 
printf&#40;" bmAttributes&#58; %02xh\n", config->bmAttributes&#41;; 
printf&#40;" MaxPower&#58; %d\n", config->MaxPower&#41;; 

for &#40;i = 0; i < config->bNumInterfaces; i++&#41; 
print_interface&#40;&config->interface&#91;i&#93;&#41;; 
&#125; 


int main&#40;void&#41; 
&#123; 
struct usb_bus *bus; 
struct usb_device *dev; 

usb_init&#40;&#41;; 
usb_find_busses&#40;&#41;; 
usb_find_devices&#40;&#41;; 

printf&#40;"bus/device idVendor/idProduct\n"&#41;; 

for &#40;bus = usb_busses; bus; bus = bus->next&#41; &#123; 
for &#40;dev = bus->devices; dev; dev = dev->next&#41; &#123; 
int ret, i; 
char string&#91;256&#93;; 
usb_dev_handle *udev; 

printf&#40;"%s/%s %04X/%04X\n", bus->dirname, dev->filename, 
dev->descriptor.idVendor, dev->descriptor.idProduct&#41;; 

udev = usb_open&#40;dev&#41;; 
if &#40;udev&#41; &#123; 
if &#40;dev->descriptor.iManufacturer&#41; &#123; 
ret = usb_get_string_simple&#40;udev, dev->descriptor.iManufacturer, string, sizeof&#40;string&#41;&#41;; 
if &#40;ret > 0&#41; 
printf&#40;"- Manufacturer &#58; %s\n", string&#41;; 
else 
printf&#40;"- Unable to fetch manufacturer string\n"&#41;; 
&#125; 

if &#40;dev->descriptor.iProduct&#41; &#123; 
ret = usb_get_string_simple&#40;udev, dev->descriptor.iProduct, string, sizeof&#40;string&#41;&#41;; 
if &#40;ret > 0&#41; 
printf&#40;"- Product &#58; %s\n", string&#41;; 
else 
printf&#40;"- Unable to fetch product string\n"&#41;; 
&#125; 

if &#40;dev->descriptor.iSerialNumber&#41; &#123; 
ret = usb_get_string_simple&#40;udev, dev->descriptor.iSerialNumber, string, sizeof&#40;string&#41;&#41;; 
if &#40;ret > 0&#41; 
printf&#40;"- Serial Number&#58; %s\n", string&#41;; 
else 
printf&#40;"- Unable to fetch serial number string\n"&#41;; 
&#125; 

usb_close &#40;udev&#41;; 
&#125; 

if &#40;!dev->config&#41; &#123; 
printf&#40;" Couldn't retrieve descriptors\n"&#41;; 
continue; 
&#125; 

for &#40;i = 0; i < dev->descriptor.bNumConfigurations; i++&#41; 
print_configuration&#40;&dev->config&#91;i&#93;&#41;; 
&#125; 
&#125; 

return 0; 
&#125;
The above program should be compiled as

(root$)gcc -o usbdevice_details testlibusb.c -I/usr/local/include -L. -lnsl -lm -lc -L/usr/local/lib -lusb

(root$)./usbdevice_details (enter)


Following is the output of the above command ,its the listing of a USB pen drive connected to my system.

The first line displays the bus-name/device-name & device-id/product-id and rest of the listing is self-descriptive.

Code:
001/004 0EA0/2168 
- Manufacturer &#58; USB 
- Product &#58; Flash Disk 
- Serial Number&#58; 4CE45C4E403EE53D 
wTotalLength&#58; 39 
bNumInterfaces&#58; 1 
bConfigurationValue&#58; 1 
iConfiguration&#58; 0 
bmAttributes&#58; 80h 
MaxPower&#58; 100 
bInterfaceNumber&#58; 0 
bAlternateSetting&#58; 0 
bNumEndpoints&#58; 3 
bInterfaceClass&#58; 8 
bInterfaceSubClass&#58; 6 
bInterfaceProtocol&#58; 80 
iInterface&#58; 0 
bEndpointAddress&#58; 81h 
bmAttributes&#58; 02h 
wMaxPacketSize&#58; 64 
bInterval&#58; 0 
bRefresh&#58; 0 
bSynchAddress&#58; 0 
bEndpointAddress&#58; 02h 
bmAttributes&#58; 02h 
wMaxPacketSize&#58; 64 
bInterval&#58; 0 
bRefresh&#58; 0 
bSynchAddress&#58; 0 
bEndpointAddress&#58; 83h 
bmAttributes&#58; 03h 
wMaxPacketSize&#58; 2 
bInterval&#58; 1 
bRefresh&#58; 0 
bSynchAddress&#58; 0
Before executing the above program download the current version of Libusb library from, http://http://libusb.sourceforge.net/. The above program can also be found under the tests directory of Libusb directory (after u install it)

Now I will explain in breif some of the functions and attributes dealt in the above program.

usb_init() - Used to initialize Libusb and establish connection with kernel structures .
usb_find_busses() - Looks for all the USB busses on the computer.
usb_find_devices() - Looks for all the USB devices connected to the computer.
usb_open(dev) - Opens the device 'dev' which is given as argument to this function.
usb_get_string_simple() - Used to extract the string descriptor of the device taken argument.

Important attributes of USB devices useful in device driver coding
Configuration and Endpoints are one of the two important descriptors of any USB device. These desciptors are defined using the “struct usb_config_descriptor” and “struct_usb_endpoint_descriptor” respectively .

dev->descriptor.idVendor : Reveals the Vendor-Id of the USB device connected to the system.

dev->descriptor.idProduct : Reveals the Product-Id of the USB device connected to the system.

dev->descriptor.iManufacturer : Reveals the name of the Manufacturer USB device connected to the system.

EndpointAddress:Combination of endpoint address and enpoint direction on a USB device.

InterfaceNumber : One of the several interfaces that is allocated to the connected USB device.

AlternateSetting:This is part of the a single interface allocated to the USB device.


Prerequites for Libusb programming
Linux system with Kernel 2.4 above series.
Proficiency in C language.
Good understanding of USB device internals.
Idea about USBFS.



Hope this HOWTO has enlightened you about Libusb API and I expect this HOWTO will give you a headstart in your device driver programming endeavour .This HOWTO is just an introduction to Libusb ,for complete documentation please goto http://http://libusb.sourceforge.net/

About Myself
My name is Vikram C , Im a linux freak and currently working as Linux developer in the city of Hyderabad India.You can reach me at vikram_147@hotmail.com / vikram@asrttechnologies.com