sandeep
sandeep

Reputation: 11

USB applications using libusb library

I want to use libusb library for writing some test applications for USB. Can any one please suggest how to set control transfers using usb_control_msg call?

I am getting bad descriptor error while running the following code.

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "usb.h"
static int vendor_id;
static int product_id;

typedef struct{
    int requesttype; 
    int request;
    int value;
    int index; 
    char *bytes;
    int size;
    int timeout;
}ctrlmsg_param;

void print_endpoint(struct usb_endpoint_descriptor *endpoint)
{
    printf("=====End point Information====\n");
    printf("bEndpointAddress: %x\n", endpoint->bEndpointAddress);
    printf("bmAttributes:     %x\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("\n=====Alternate Setting Information====\n");
    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 (i = 0; i < interface->bNumEndpoints; i++)
        print_endpoint(&interface->endpoint[i]);
}

void print_interface(struct usb_interface *interface)
{
    int i;

    for (i = 0; i < interface->num_altsetting; i++)
        print_altsetting(&interface->altsetting[i]);
}

void print_configuration(struct usb_config_descriptor *config)
{
    int i;

    printf("=====Configuration Information====\n");
    printf("wTotalLength:         %d\n", config->wTotalLength);
    printf("bNumInterfaces:       %d\n", config->bNumInterfaces);
    printf("bConfigurationValue:  %d\n", config->bConfigurationValue);
    printf("iConfiguration:       %d\n", config->iConfiguration);
    printf("bmAttributes:         %x\n", config->bmAttributes);
    printf("MaxPower:             %d\n", config->MaxPower);

    for (i = 0; i < config->bNumInterfaces; i++)
        print_interface(&config->interface[i]);
}

int print_device(struct usb_device *dev)
{
    usb_dev_handle *udev;
    char str[100];
    int ret, i;
    udev = usb_open(dev);
    if (udev) {
        if (dev->descriptor.iManufacturer) {
            ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer, str, sizeof(str));
            if (ret > 0)
            {
                printf("Manufacturer is %s\n",str);
            }
        }
        if (dev->descriptor.iProduct) {
            ret = usb_get_string_simple(udev, dev->descriptor.iProduct, str, sizeof(str));
            if (ret > 0)
            {
                printf("Product is %s\n",str);
            }
        } 

    }

    if (udev)
        usb_close(udev);
    printf("Possible configurations are %x\n",dev->descriptor.bNumConfigurations);
    sleep(2);
    for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
        print_configuration(&dev->config[i]);

    return 0;
}
int htod( const char* str )
{
    int decimal;
    sscanf( str, "%x", &decimal);
    return decimal;
}
void set_data(struct usb_device *dev)
{

ctrlmsg_param  param;
param.requesttype= 0;
param.request=0;
param.value=0;
param.index=0;
param.bytes=10;
param.size=0;
param.timeout=5000;
usb_control_msg(dev, param.requesttype, param.request, param.value, param.index, param.bytes, param.size, param.timeout);
printf("error is %s\n",strerror(errno));
return;

}
int main(int argc, char *argv[])
{
    struct usb_bus *bus;
    struct usb_device *dev;

    if(argc != 3)
    {
        printf("Error in number of arguments\n");
        printf("Usage:./usb_info <vendor id> <product id>\n");
        exit(0);
    }

    vendor_id=htod(argv[1]);
    product_id=htod(argv[2]);

    printf("initializing USB library\n");
    usb_init();

    printf("Finding Buses and Devices\n");
    usb_find_busses();
    usb_find_devices();

    for (bus = usb_get_busses(); bus; bus = bus->next) {
        for (dev = bus->devices; dev; dev = dev->next) {
            if ((dev->descriptor.idProduct == product_id) && (dev->descriptor.idVendor == vendor_id)){           
                printf("Found device with produxt id %x and vendor id %x\n",product_id,vendor_id);
                print_device(dev);
                set_data(dev);
                print_device(dev);
            }
        }
    }
    return 0;
}

Regards, Sandeep

Upvotes: 1

Views: 2363

Answers (1)

David M
David M

Reputation: 31

I think that you mean usb_control_msg() is returns an error code for "bad descriptor". Please clarify if this is incorrect.

USB control transfers have some very specific formatting rules, and if the packet you are forming is sent to any compliant device, it will return a request error / stall on the bus.

You are sending the control transfer:

bmRequestType = 0x00
bRequest      = 0x00
wValue        = 0x0000
wIndex        = 0x0000
wSize         = 0x0000

this should be interpreted by the USB device as a GET_STATUS request, so wLength is required to be 2, and bmRequestType needs to have the top bit set, indicating this is an IN direction request (from the host's point of view). This is all from Chapter 9 of the USB specification 1.1/2.0/3.1 available at www.usb.org.

The parameter char *bytes (your param.bytes) also needs to be an address/pointer in the call you are making.

A good standard control transfer to test with would be:

bmRequestType = 0x80
bRequest      = 0x06
wValue        = 0x0001
wIndex        = 0x0000
wSize         = 0x0008

This request will return the first 8 bytes of the Device Descriptor, it is valid for every USB device, in all states.

The other transfer types (bulk, interrupt) don't have these strict formatting rules, and can be an easier place to start. I'd imagine you have already moved past this issue, since the question has been posted for quite a while, but maybe this response will still help someone else.

Upvotes: 2

Related Questions