0

I'm currently trying to make a little piece of code that receive and send data to a HID (Texas Instrument HDK). There is no bug on the embedded system code (i can send data with a java program on mac OS to the device).

The reception is working but i can't send data (always getting error io return code).

Here's the code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
#include "libusb.h"

const static int PACKET_INT_LEN = 4;
const static int INTERFACE = 0;
const static int ENDPOINT_INT_IN = 0x83;  /* endpoint 3 address for IN */
const static int ENDPOINT_INT_OUT = 0x04; /* endpoint 4 address for OUT */
const static int TIMEOUT = 5000; 

#pragma comment(lib, "libusb-1.0.lib")

using namespace std; 

libusb_device ** DoList();
libusb_device_handle * GetDevice(libusb_device ** deviceList);
int test_interrupt_transfer(libusb_device_handle * devh);
void error_interrupt_transfert(int r);

int main()
{
    libusb_context ** context = NULL;

    libusb_device_handle * deviceHandle = NULL;

    int result_init = 0;

    result_init = libusb_init(context);

    if (result_init < 0)
        cout << "Failed to init libusb." << endl;
    else
        deviceHandle = GetDevice(DoList());

    int err = libusb_kernel_driver_active(deviceHandle, 0); 
    if (err >= LIBUSB_SUCCESS)
    {
        if (err == 1)
        {
            printf("Kernel driver is active, trying to detach"); 
            err = libusb_detach_kernel_driver(deviceHandle, 0);

            if (err != LIBUSB_SUCCESS)
            {
                printf("Error detaching interface from kernel");
            }
        }
    }

    if (libusb_kernel_driver_active(deviceHandle, 0) == 1)
    {
        if (libusb_detach_kernel_driver(deviceHandle, 0) == 0)
            cout << "Kernel driver detatched !" << endl; 
    }
    while (1)
    {
        test_interrupt_transfer(deviceHandle);

        cout << 1 << endl; 
        Sleep(3000); 
    }

    system("pause");
}

libusb_device ** DoList()
{
    libusb_device **devs;
    ssize_t count; 

    count = libusb_get_device_list(NULL, &devs); 
    if (count < 0)
    {
        cout << "Failed to get device list";
        return NULL;
    }
    libusb_device *dev;
    int i = 0; 

    cout << "Device list" << endl;
    while ((dev = devs[i++]) != NULL)
    {
        struct libusb_device_descriptor desc;
        int r = libusb_get_device_descriptor(dev, &desc); 

        if (r < 0)
        {
            cout << "Failed to get device descriptor" << endl;
            return NULL; 
        }
        printf("\t%04x:%04x (bus %d, device %d)\n",
                desc.idVendor, desc.idProduct,
                libusb_get_bus_number(dev), libusb_get_device_address(dev));
    }
    return devs;
}

libusb_device_handle * GetDevice(libusb_device ** devList)
{
    int i = 0,
        vid = 0x1cbe,
        pid = 0;
    libusb_device * dev;
    libusb_device_handle * handle = NULL;
    unsigned char strDesc[256];

    if (devList == NULL)
    {
        return NULL;
    }

    while ((dev = devList[i++]) != NULL)
    {
        struct libusb_device_descriptor desc;
        struct libusb_config_descriptor ** conDesc = NULL;

        int ret = libusb_get_device_descriptor(dev, &desc); 
        if (ret < 0)
        {
            cout << "Failed libusb_get_device_descriptor" << endl; 
            continue; 
        }
        if (desc.idVendor == vid && desc.idProduct == pid)
        {
            int ret = libusb_open(dev, &handle); 
            if (ret < 0)
            {
                cout << "Failed libusb_open" << ret << endl; 
                break; 
            }

            ret = libusb_claim_interface(handle, 0); 
            if (ret < 0)
            {
                cout << "Failed libusb_claim_interface" << endl; 
                libusb_close(handle);
                handle = NULL;
                break;
            }

            libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, strDesc, 256);
            printf("     Manufacturer = %s\n", strDesc);

            libusb_get_string_descriptor_ascii(handle, desc.iProduct, strDesc, 256);
            printf("     Product = %s\n", strDesc);

            libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, strDesc, 256);
            printf("     Serial number = %s\n", strDesc);
            break; 
        }
    }
    cout << "Success openning device" << endl; 

    libusb_free_device_list(devList, 1);
    return handle; 
}

int test_interrupt_transfer(libusb_device_handle * devh)
{
    int r, i;
    int transferred = 0;
    int * ptransferred = &transferred;
    unsigned char answer[PACKET_INT_LEN];
    unsigned char question[2];

    r = libusb_interrupt_transfer(devh, ENDPOINT_INT_OUT, question,
                                  sizeof(question), ptransferred, TIMEOUT);
    if (r < 0) {
        error_interrupt_transfert(r);
        return r;
    }

    r = libusb_interrupt_transfer(devh, ENDPOINT_INT_IN, answer, PACKET_INT_LEN,
        &transferred, TIMEOUT);
    if (r < 0) 
    {
        error_interrupt_transfert(r);
        return r;
    }

    for (i = 0; i < PACKET_INT_LEN; i++) 
    {
        printf("%02x; ", answer[i]);
    }
    printf("\n");
    return 0;
}

void error_interrupt_transfert(int r)
{
    switch (r)
    {
    case LIBUSB_SUCCESS: cout << "Success" << endl; 
        break; 
    case LIBUSB_ERROR_TIMEOUT: cout << "Timeout" << endl;
        break;
    case LIBUSB_ERROR_PIPE: cout << "Error pipe" << endl;
        break;
    case LIBUSB_ERROR_OVERFLOW: cout << "Overflow" << endl;
        break;
    case LIBUSB_ERROR_NO_DEVICE: cout << "No device" << endl;
        break;
    case LIBUSB_ERROR_IO: cout << "Error IO" << endl;
        break;
    case LIBUSB_ERROR_NOT_FOUND: cout << "Not found" << endl; 
        break; 
    case LIBUSB_ERROR_INVALID_PARAM: cout << "Invalid param" << endl;
        break; 
    case LIBUSB_ERROR_ACCESS: cout << "Error access" << endl; 
        break; 
    case LIBUSB_ERROR_INTERRUPTED: cout << "Interrupted" << endl; 
        break;
    case LIBUSB_ERROR_BUSY: cout << "Busy" << endl; 
        break; 
    case LIBUSB_ERROR_NO_MEM: cout << "No memory" << endl; 
        break; 
    case LIBUSB_ERROR_NOT_SUPPORTED: cout << "Not supported" << endl; 
        break; 
    case LIBUSB_ERROR_OTHER: cout << "Other" << endl;
        break; 
    default: cout << "Unknow error code" << r << endl;
    }
}

Any idea folks?

Calmant Kévin

  • There are some questions concerning this: Has the device any descriptor for the OUT endpoint and what does it say about the endpoint? Have you tried explicitly setting a configuration? Also you should use libusb_ref_device on any device you want to use before freeing the device list with unref set. – dryman Apr 25 '16 at 12:23
  • Hello, Yeah there is descriptor for the OUT endpoint and the info i get from Device Monitoring Studio are 0x4 Output Interrupt with max packet size : 64 bytes. I don't understand what do you mean by explicitly setting a configuration. I've just tried to ref the device i want to use, this has no effect on the error. However i've just added libusb_set_debug on my code and the error isn't IO_ERROR but `libusb: debug [hid_submit_bulk_transfer] HID transfer failed: [1] Invalid function.` – Kévin Calmant Apr 25 '16 at 13:14
  • About the configuration: Some devices have more than 1 configuration and therefore setting a configuration is a normal procedure to avoid troubles if the device has been set to the wrong configuration beforehand. libusb_set_configuration can be used for that (normally the index is 1-based but some devices not implementing the spec correctly may have a configuration 0). What bothers me is why it still has anything to do with the HID. What backend do you use (WinUSB, libusb0, libusbK)? – dryman Apr 25 '16 at 14:49
  • I'm using libusb and just read on their website that i can't use the library for a HID class device ... I will have to search another library that that can interface with HID without modifying the default driver – Kévin Calmant Apr 26 '16 at 07:26
  • Yes if you use libusb you have to implement the HID relevant logic yourself. You only get the raw HID data. – dryman Apr 26 '16 at 07:31
  • Have you any info on how to implement this HID logic on libusb? – Kévin Calmant Apr 26 '16 at 13:37
  • The thing is in my case the HID logic itself was made by a colleague. How to interpret the commands is dependent on what device you want to use (keyboard, mouse, gamepad and so on). But with USB the best place to go is usb.org. They have a general HID spec that defines how it works in general: http://www.usb.org/developers/hidpage/HID1_11.pdf. And for already declared types they have a usage table as mapping of codes to keys/moves/clicks ando so on: http://www.usb.org/developers/hidpage/Hut1_12v2.pdf – dryman Apr 28 '16 at 08:10
  • An alternative would be to use a HID library like http://www.signal11.us/oss/hidapi/ that have implemented it already. – dryman Apr 28 '16 at 08:10

0 Answers0