Windows application using libusb: runtime error due to mutex lock

902 views Asked by At

I am trying to establish communication between a laptop and an embedded board over USB. USB driver for board has been installed and it has been detected in Windows device manager. Now I am developing code in Visual Studio 2013 (Win32 Console Application) using libusb.

The libusb_init() function does not return an error however when I try to open the device with libusb_open_device_with_vid_pid(), execution breaks at function usbi_mutex_init() in the threads_windows.c file of the libusb library. This file contains the source for "libusb synchronization on Microsoft Windows".

I also tried to call function libusb_get_device_list() but get the same error. Could you please suggest a solution?

main.cpp from my application source code -->

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

using namespace std;

int main()
{
 int init_status = 0;
 libusb_context *context = NULL;
 libusb_device_handle *device;

 init_status = libusb_init(&context);
 if (init_status<0)
 {
    cout << "could not initialize";
    return -1;
 }

 device = libusb_open_device_with_vid_pid(NULL, 0x0483, 0x5750); //execution breaks here
 if (device == NULL)
 {
    cout << "could not open device";
    return -1;
 }
 else
 {
    cout << "Device opened successfukky";
 }

 return 0;
}

threads_windows.c from libusb source code -->

int usbi_mutex_lock(usbi_mutex_t *mutex) {
    DWORD result;
    if(!mutex) return ((errno=EINVAL));
    result = WaitForSingleObject(*mutex, INFINITE);  //execution breaks here
    if(result == WAIT_OBJECT_0 || result == WAIT_ABANDONED)
        return 0; // acquired (ToDo: check that abandoned is ok)
    return ((errno=EINVAL)); // don't know how this would happen
                         //   so don't know proper errno
}
1

There are 1 answers

0
Richard Chambers On

Looks to me like you get a specific, non-default context with your libusb_init() but when you use libusb_open_device_with_vid_pid() you are pass NULL which means to use the default context rather than the context created by the libusb_init().

You may just want to use the default context if it is a single device and you only need a single session. The documentation indicates that there are "limitations" with libusb_open_device_with_vid_pid() and it is not intended for anything other than test applications. I assume this is because in real applications there may be multiple devices and this convenience function just takes the first one matching the arguments. However the issue you are seeing is probably related to the context.

For a one off type of specific project your code would look something like:

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

using namespace std;

int main()
{
    int init_status = 0;
    libusb_device_handle *device;

    // specify NULL for the context address so that libusb_init will use default content.
    // this means that any libusb function with a context argument will be called with NULL.
    init_status = libusb_init (NULL);
    if (init_status < 0)
    {
        cout << "could not initialize";
        return -1;
    }
    // open the first device found in the device list with this vendor id and product id
    // for a real application in a multi-device environment we would need to
    // iterate through the various devices using libusb_get_device_list() to get
    // the list of devices then using libusb_get_device_descriptor() to iterate
    // through the list to find the device we want. also need libusb_free_device_list   ()
    // after finishing with the list.  lots of work for a simple one off project
    device = libusb_open_device_with_vid_pid (NULL, 0x0483, 0x5750);
    if (device == NULL)
    {
        cout << "could not open device";
        return -1;
    } else {
        cout << "Device opened successfully";
    }

    return 0;
}